private void skipToField(JsonParser jp, String fieldName, ParseState state) throws JsonParseException, IOException { String lastFieldName = null; while (jp.getCurrentToken() != null) { switch (jp.getCurrentToken()) { case FIELD_NAME: lastFieldName = jp.getCurrentName(); jp.nextToken(); break; case START_OBJECT: if (!state.inRow) { state.inRow = true; jp.nextToken(); } else { if (isInField(fieldName, lastFieldName)) { return; } else { jp.skipChildren(); } } break; default: if (isInField(fieldName, lastFieldName)) { jp.nextToken(); return; } jp.nextToken(); break; } } }
@Override public DateMidnight deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { // We'll accept either long (timestamp) or array: if (jp.isExpectedStartArrayToken()) { jp.nextToken(); // VALUE_NUMBER_INT int year = jp.getIntValue(); jp.nextToken(); // VALUE_NUMBER_INT int month = jp.getIntValue(); jp.nextToken(); // VALUE_NUMBER_INT int day = jp.getIntValue(); if (jp.nextToken() != JsonToken.END_ARRAY) { throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY, "after DateMidnight ints"); } return new DateMidnight(year, month, day); } switch (jp.getCurrentToken()) { case VALUE_NUMBER_INT: return new DateMidnight(jp.getLongValue()); case VALUE_STRING: DateTime local = parseLocal(jp); if (local == null) { return null; } return local.toDateMidnight(); } throw ctxt.wrongTokenException( jp, JsonToken.START_ARRAY, "expected JSON Array, Number or String"); }
private Map<String, Integer> readHeaderFields(JsonParser jp) throws JsonParseException, IOException { Map<String, Integer> map = new HashMap<String, Integer>(); jp.nextToken(); String nextFieldName = jp.getCurrentName(); while (!nextFieldName.equals(ROWS_FIELD_NAME)) { jp.nextToken(); map.put(nextFieldName, Integer.valueOf(jp.getIntValue())); jp.nextToken(); nextFieldName = jp.getCurrentName(); } return map; }
@Override public EnumMap<?, ?> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { // Ok: must point to START_OBJECT if (jp.getCurrentToken() != JsonToken.START_OBJECT) { return _deserializeFromEmpty(jp, ctxt); } EnumMap result = constructMap(); final JsonDeserializer<Object> valueDes = _valueDeserializer; final TypeDeserializer typeDeser = _valueTypeDeserializer; while ((jp.nextToken()) == JsonToken.FIELD_NAME) { String keyName = jp.getCurrentName(); // just for error message // but we need to let key deserializer handle it separately, nonetheless Enum<?> key = (Enum<?>) _keyDeserializer.deserializeKey(keyName, ctxt); if (key == null) { if (!ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) { throw ctxt.weirdStringException( keyName, _enumClass, "value not one of declared Enum instance names for " + _mapType.getKeyType()); } /* 24-Mar-2012, tatu: Null won't work as a key anyway, so let's * just skip the entry then. But we must skip the value as well, if so. */ jp.nextToken(); jp.skipChildren(); continue; } // And then the value... JsonToken t = jp.nextToken(); /* note: MUST check for nulls separately: deserializers will * not handle them (and maybe fail or return bogus data) */ Object value; try { if (t == JsonToken.VALUE_NULL) { value = valueDes.getNullValue(ctxt); } else if (typeDeser == null) { value = valueDes.deserialize(jp, ctxt); } else { value = valueDes.deserializeWithType(jp, ctxt, typeDeser); } } catch (Exception e) { wrapAndThrow(e, result, keyName); return null; } result.put(key, value); } return result; }
@Override public LocalDateTime deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { // We'll accept either long (timestamp) or array: if (jp.isExpectedStartArrayToken()) { jp.nextToken(); // VALUE_NUMBER_INT int year = jp.getIntValue(); jp.nextToken(); // VALUE_NUMBER_INT int month = jp.getIntValue(); jp.nextToken(); // VALUE_NUMBER_INT int day = jp.getIntValue(); jp.nextToken(); // VALUE_NUMBER_INT int hour = jp.getIntValue(); jp.nextToken(); // VALUE_NUMBER_INT int minute = jp.getIntValue(); jp.nextToken(); // VALUE_NUMBER_INT int second = jp.getIntValue(); // let's leave milliseconds optional? int millisecond = 0; if (jp.nextToken() != JsonToken.END_ARRAY) { // VALUE_NUMBER_INT millisecond = jp.getIntValue(); jp.nextToken(); // END_ARRAY? } if (jp.getCurrentToken() != JsonToken.END_ARRAY) { throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY, "after LocalDateTime ints"); } return new LocalDateTime(year, month, day, hour, minute, second, millisecond); } switch (jp.getCurrentToken()) { case VALUE_NUMBER_INT: return new LocalDateTime(jp.getLongValue()); case VALUE_STRING: DateTime local = parseLocal(jp); if (local == null) { return null; } return local.toLocalDateTime(); } throw ctxt.wrongTokenException(jp, JsonToken.START_ARRAY, "expected JSON Array or Number"); }
private Object success(Class<?> clazz, HttpInputMessage inputMessage) throws JsonParseException, IOException { // Note, parsing code used from ektorp project JsonParser jp = objectMapper.getJsonFactory().createJsonParser(inputMessage.getBody()); if (jp.nextToken() != JsonToken.START_OBJECT) { throw new RuntimeException("Expected data to start with an Object"); } Map<String, Integer> fields = readHeaderFields(jp); List result; if (fields.containsKey(TOTAL_ROWS_FIELD_NAME)) { int totalRows = fields.get(TOTAL_ROWS_FIELD_NAME); if (totalRows == 0) { return Collections.emptyList(); } result = new ArrayList(totalRows); } else { result = new ArrayList(); } ParseState state = new ParseState(); Object first = parseFirstRow(jp, state, clazz); if (first == null) { return Collections.emptyList(); } else { result.add(first); } while (jp.getCurrentToken() != null) { skipToField(jp, state.docFieldName, state); if (atEndOfRows(jp)) { return result; } result.add(jp.readValueAs(clazz)); endRow(jp, state); } return result; }
private Object parseFirstRow(JsonParser jp, ParseState state, Class clazz) throws JsonParseException, IOException, JsonProcessingException, JsonMappingException { skipToField(jp, VALUE_FIELD_NAME, state); JsonNode value = null; if (atObjectStart(jp)) { value = jp.readValueAsTree(); jp.nextToken(); if (isEndOfRow(jp)) { state.docFieldName = VALUE_FIELD_NAME; Object doc = objectMapper.readValue(value, clazz); endRow(jp, state); return doc; } } skipToField(jp, INCLUDED_DOC_FIELD_NAME, state); if (atObjectStart(jp)) { state.docFieldName = INCLUDED_DOC_FIELD_NAME; Object doc = jp.readValueAs(clazz); endRow(jp, state); return doc; } return null; }
private void endRow(JsonParser jp, ParseState state) throws IOException, JsonParseException { state.inRow = false; jp.nextToken(); }