if (p.canReadTypeId()) { Object typeId = p.getTypeId(); if (typeId != null) { return _deserializeWithNativeTypeId(p, ctxt, typeId); boolean hadStartArray = p.isExpectedStartArrayToken(); String typeId = _locateTypeId(p, ctxt); JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId); && p.getCurrentToken() == JsonToken.START_OBJECT) { TokenBuffer tb = new TokenBuffer(null, false); tb.writeStartObject(); // recreate START_OBJECT tb.writeFieldName(_typePropertyName); tb.writeString(typeId); p.clearCurrentToken(); p = JsonParserSequence.createFlattened(false, tb.asParser(p), p); p.nextToken(); Object value = deser.deserialize(p, ctxt); if (hadStartArray && p.nextToken() != JsonToken.END_ARRAY) { ctxt.reportWrongTokenException(baseType(), JsonToken.END_ARRAY, "expected closing END_ARRAY after type information and deserialized value");
/** * Method that will construct a parser (possibly a sequence) that * contains all given sub-parsers. * All parsers given are checked to see if they are sequences: and * if so, they will be "flattened", that is, contained parsers are * directly added in a new sequence instead of adding sequences * within sequences. This is done to minimize delegation depth, * ideally only having just a single level of delegation. */ public static JsonParserSequence createFlattened(boolean checkForExistingToken, JsonParser first, JsonParser second) { if (!(first instanceof JsonParserSequence || second instanceof JsonParserSequence)) { return new JsonParserSequence(checkForExistingToken, new JsonParser[] { first, second }); } ArrayList<JsonParser> p = new ArrayList<JsonParser>(); if (first instanceof JsonParserSequence) { ((JsonParserSequence) first).addFlattenedActiveParsers(p); } else { p.add(first); } if (second instanceof JsonParserSequence) { ((JsonParserSequence) second).addFlattenedActiveParsers(p); } else { p.add(second); } return new JsonParserSequence(checkForExistingToken, p.toArray(new JsonParser[p.size()])); }
@Override public void close() throws IOException { do { delegate.close(); } while (switchToNext()); }
@Override public String nextFieldName() throws IOException { // NOTE: call `nextToken()` to handle delegation return (nextToken() == JsonToken.FIELD_NAME) ? currentName() : null; }
@SuppressWarnings("resource") protected Object _deserializeTypedForId(JsonParser p, DeserializationContext ctxt, TokenBuffer tb) throws IOException { String typeId = p.getText(); JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId); if (_typeIdVisible) { // need to merge id back in JSON input? if (tb == null) { tb = new TokenBuffer(p, ctxt); } tb.writeFieldName(p.getCurrentName()); tb.writeString(typeId); } if (tb != null) { // need to put back skipped properties? // 02-Jul-2016, tatu: Depending on for JsonParserSequence is initialized it may // try to access current token; ensure there isn't one p.clearCurrentToken(); p = JsonParserSequence.createFlattened(false, tb.asParser(p), p); } // Must point to the next value; tb had no current, jp pointed to VALUE_STRING: p.nextToken(); // to skip past String value // deserializer should take care of closing END_OBJECT as well return deser.deserialize(p, ctxt); }
@Override public JsonToken nextToken() throws IOException { if (delegate == null) { return null; } if (_hasToken) { _hasToken = false; return delegate.currentToken(); } JsonToken t = delegate.nextToken(); if (t == null) { return switchAndReturnNext(); } return t; }
@Override public JsonToken nextToken() throws IOException, JsonParseException { JsonToken t = delegate.nextToken(); if (t != null) return t; while (switchToNext()) { t = delegate.nextToken(); if (t != null) return t; } return null; }
/** * Need to override, re-implement similar to how method defined in * {@link com.fasterxml.jackson.core.base.ParserMinimalBase}, to keep * state correct here. */ @Override public JsonParser skipChildren() throws IOException { if ((delegate.currentToken() != JsonToken.START_OBJECT) && (delegate.currentToken() != JsonToken.START_ARRAY)) { return this; } int open = 1; // Since proper matching of start/end markers is handled // by nextToken(), we'll just count nesting levels here while (true) { JsonToken t = nextToken(); if (t == null) { // not ideal but for now, just return return this; } if (t.isStructStart()) { ++open; } else if (t.isStructEnd()) { if (--open == 0) { return this; } } } }
@SuppressWarnings("resource") protected void addFlattenedActiveParsers(List<JsonParser> listToAddIn) { for (int i = _nextParserIndex-1, len = _parsers.length; i < len; ++i) { JsonParser p = _parsers[i]; if (p instanceof JsonParserSequence) { ((JsonParserSequence) p).addFlattenedActiveParsers(listToAddIn); } else { listToAddIn.add(p); } } }
/** * @deprecated Since 2.8 use {@link #createFlattened(boolean, JsonParser, JsonParser)} * instead */ @Deprecated // since 2.8 public static JsonParserSequence createFlattened(JsonParser first, JsonParser second) { return createFlattened(false, first, second); }
@SuppressWarnings("resource") protected final Object _deserializeTypedForId(JsonParser jp, DeserializationContext ctxt, TokenBuffer tb) throws IOException { String typeId = jp.getText(); JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId); if (_typeIdVisible) { // need to merge id back in JSON input? if (tb == null) { tb = new TokenBuffer(null, false); } tb.writeFieldName(jp.getCurrentName()); tb.writeString(typeId); } if (tb != null) { // need to put back skipped properties? jp = JsonParserSequence.createFlattened(tb.asParser(jp), jp); } // Must point to the next value; tb had no current, jp pointed to VALUE_STRING: jp.nextToken(); // to skip past String value // deserializer should take care of closing END_OBJECT as well return deser.deserialize(jp, ctxt); }
@Override public JsonToken nextToken() throws IOException { if (delegate == null) { return null; } if (_hasToken) { _hasToken = false; return delegate.currentToken(); } JsonToken t = delegate.nextToken(); if (t == null) { return switchAndReturnNext(); } return t; }
@Override public JsonToken nextToken() throws IOException, JsonParseException { JsonToken t = delegate.nextToken(); if (t != null) return t; while (switchToNext()) { t = delegate.nextToken(); if (t != null) return t; } return null; }
/** * Need to override, re-implement similar to how method defined in * {@link com.fasterxml.jackson.core.base.ParserMinimalBase}, to keep * state correct here. */ @Override public JsonParser skipChildren() throws IOException { if ((delegate.currentToken() != JsonToken.START_OBJECT) && (delegate.currentToken() != JsonToken.START_ARRAY)) { return this; } int open = 1; // Since proper matching of start/end markers is handled // by nextToken(), we'll just count nesting levels here while (true) { JsonToken t = nextToken(); if (t == null) { // not ideal but for now, just return return this; } if (t.isStructStart()) { ++open; } else if (t.isStructEnd()) { if (--open == 0) { return this; } } } }
@SuppressWarnings("resource") protected void addFlattenedActiveParsers(List<JsonParser> listToAddIn) { for (int i = _nextParserIndex-1, len = _parsers.length; i < len; ++i) { JsonParser p = _parsers[i]; if (p instanceof JsonParserSequence) { ((JsonParserSequence) p).addFlattenedActiveParsers(listToAddIn); } else { listToAddIn.add(p); } } }
/** * @deprecated Since 2.8 use {@link #createFlattened(boolean, JsonParser, JsonParser)} * instead */ @Deprecated // since 2.8 public static JsonParserSequence createFlattened(JsonParser first, JsonParser second) { return createFlattened(false, first, second); }
@Override public boolean nextFieldName(SerializableString str) throws IOException { // NOTE: call `nextToken()` to handle delegation return (nextToken() == JsonToken.FIELD_NAME) && str.getValue().equals(currentName()); }
if (p.canReadTypeId()) { Object typeId = p.getTypeId(); if (typeId != null) { return _deserializeWithNativeTypeId(p, ctxt, typeId); JsonToken t = p.getCurrentToken(); if (t == JsonToken.START_OBJECT) { if (p.nextToken() != JsonToken.FIELD_NAME) { ctxt.reportWrongTokenException(baseType(), JsonToken.FIELD_NAME, "need JSON String that contains type id (for subtype of "+baseTypeName()+")"); ctxt.reportWrongTokenException(baseType(), JsonToken.START_OBJECT, "need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName()); if (_typeIdVisible && p.getCurrentToken() == JsonToken.START_OBJECT) { p.clearCurrentToken(); p = JsonParserSequence.createFlattened(false, tb.asParser(p), p); p.nextToken(); Object value = deser.deserialize(p, ctxt); if (p.nextToken() != JsonToken.END_OBJECT) { ctxt.reportWrongTokenException(baseType(), JsonToken.END_OBJECT, "expected closing END_OBJECT after type information and deserialized value");
protected final Object _deserializeTypedForId(JsonParser jp, DeserializationContext ctxt, TokenBuffer tb) throws IOException, JsonProcessingException { String typeId = jp.getText(); JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId); if (_typeIdVisible) { // need to merge id back in JSON input? if (tb == null) { tb = new TokenBuffer(null); } tb.writeFieldName(jp.getCurrentName()); tb.writeString(typeId); } if (tb != null) { // need to put back skipped properties? jp = JsonParserSequence.createFlattened(tb.asParser(jp), jp); } // Must point to the next value; tb had no current, jp pointed to VALUE_STRING: jp.nextToken(); // to skip past String value // deserializer should take care of closing END_OBJECT as well return deser.deserialize(jp, ctxt); }
@Override public JsonToken nextToken() throws IOException { if (delegate == null) { return null; } if (_hasToken) { _hasToken = false; return delegate.currentToken(); } JsonToken t = delegate.nextToken(); if (t == null) { return switchAndReturnNext(); } return t; }