private Object readField(JsonParser p,
ResourceFieldSchema field,
int fieldnum) throws IOException {
// Read the next token
JsonToken tok = p.nextToken();
if (tok == null) {
warn("Early termination of record, expected " + schema.getFields().length
+ " fields bug found " + fieldnum, PigWarning.UDF_WARNING_1);
return null;
}
// Check to see if this value was null
if (tok == JsonToken.VALUE_NULL) return null;
// Read based on our expected type
switch (field.getType()) {
case DataType.BOOLEAN:
tok = p.nextToken();
if (tok == JsonToken.VALUE_NULL) return null;
return p.getBooleanValue();
case DataType.INTEGER:
// Read the field name
tok = p.nextToken();
if (tok == JsonToken.VALUE_NULL) return null;
return p.getIntValue();
case DataType.LONG:
tok = p.nextToken();
if (tok == JsonToken.VALUE_NULL) return null;
return p.getLongValue();
case DataType.FLOAT:
tok = p.nextToken();
if (tok == JsonToken.VALUE_NULL) return null;
return p.getFloatValue();
case DataType.DOUBLE:
tok = p.nextToken();
if (tok == JsonToken.VALUE_NULL) return null;
return p.getDoubleValue();
case DataType.DATETIME:
tok = p.nextToken();
if (tok == JsonToken.VALUE_NULL) return null;
DateTimeFormatter formatter = ISODateTimeFormat.dateTimeParser();
return formatter.withOffsetParsed().parseDateTime(p.getText());
case DataType.BYTEARRAY:
tok = p.nextToken();
if (tok == JsonToken.VALUE_NULL) return null;
byte[] b = p.getText().getBytes();
// Use the DBA constructor that copies the bytes so that we own
// the memory
return new DataByteArray(b, 0, b.length);
case DataType.CHARARRAY:
tok = p.nextToken();
if (tok == JsonToken.VALUE_NULL) return null;
return p.getText();
case DataType.BIGINTEGER:
tok = p.nextToken();
if (tok == JsonToken.VALUE_NULL) return null;
return p.getBigIntegerValue();
case DataType.BIGDECIMAL:
tok = p.nextToken();
if (tok == JsonToken.VALUE_NULL) return null;
return p.getDecimalValue();
case DataType.MAP:
// Should be a start of the map object
if (p.nextToken() != JsonToken.START_OBJECT) {
warn("Bad map field, could not find start of object, field "
+ fieldnum, PigWarning.UDF_WARNING_1);
return null;
}
Map<String, String> m = new HashMap<String, String>();
while (p.nextToken() != JsonToken.END_OBJECT) {
String k = p.getCurrentName();
String v = p.getCurrentToken() == JsonToken.VALUE_NULL ? null : p.getText();
m.put(k, v);
}
return m;
case DataType.TUPLE:
if (p.nextToken() != JsonToken.START_OBJECT) {
warn("Bad tuple field, could not find start of object, "
+ "field " + fieldnum, PigWarning.UDF_WARNING_1);
return null;
}
ResourceSchema s = field.getSchema();
ResourceFieldSchema[] fs = s.getFields();
Tuple t = tupleFactory.newTuple(fs.length);
for (int j = 0; j < fs.length; j++) {
t.set(j, readField(p, fs[j], j));
}
if (p.nextToken() != JsonToken.END_OBJECT) {
warn("Bad tuple field, could not find end of object, "
+ "field " + fieldnum, PigWarning.UDF_WARNING_1);
return null;
}
return t;
case DataType.BAG:
if (p.nextToken() != JsonToken.START_ARRAY) {
warn("Bad bag field, could not find start of array, "
+ "field " + fieldnum, PigWarning.UDF_WARNING_1);
return null;
}
s = field.getSchema();
fs = s.getFields();
// Drill down the next level to the tuple's schema.
s = fs[0].getSchema();
fs = s.getFields();
DataBag bag = bagFactory.newDefaultBag();
JsonToken innerTok;
while ((innerTok = p.nextToken()) != JsonToken.END_ARRAY) {
if (innerTok != JsonToken.START_OBJECT) {
warn("Bad bag tuple field, could not find start of "
+ "object, field " + fieldnum, PigWarning.UDF_WARNING_1);
return null;