FasterXML / jackson-databind

General data-binding package for Jackson (2.x): works on streaming API (core) implementation(s)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Weird behavior when deserializing from JSON array

NoahELE opened this issue · comments

Search before asking

  • I searched in the issues and found nothing similar.

Describe the bug

I try to deserialize a Point class from an array of 2, e.g. "[1,1]".

When using JsonDeserializer, the first token read is not an JsonToken.START_ARRAY.

Version Information

2.17.0

Reproduction

public class Point {
    public int x;
    public int y;
}

public class PointDeserializer extends JsonDeserializer<Point> {
    @Override
    public Point deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JacksonException {
        if (jp.nextToken() != JsonToken.START_ARRAY) {
            throw new JsonParseException(jp, "Expected array start");
        }
        if (jp.nextToken() != JsonToken.VALUE_NUMBER_INT) {
            throw new JsonParseException(jp, "Expected int");
        }
        int x = jp.getIntValue();
        if (jp.nextToken() != JsonToken.VALUE_NUMBER_INT) {
            throw new JsonParseException(jp, "Expected int");
        }
        int y = jp.getIntValue();
        if (jp.nextToken() != JsonToken.END_ARRAY) {
            throw new JsonParseException(jp, "Expected array end");
        }
        var point = new Point();
        point.x = x;
        point.y = y;
        return point;
    }
}

public class PointJson {
    public static void main(String[] args) throws Exception {
        var objectMapper = new ObjectMapper();
        objectMapper.registerModule(new SimpleModule() {
            {
                addDeserializer(Point.class, new PointDeserializer());
            }
        });

        var json = "[1,2]";
        var point = objectMapper.readValue(json, Point.class); // Exception in thread "main" com.fasterxml.jackson.core.JsonParseException: Expected array start
        System.out.println(point);
    }
}

Expected behavior

The first token should be an array start. It seems to be skipped.

Additional context

No response

This should perhaps be documented better, but the contract for custom deserializer is that the CURRENT token JsonParser points to is the first token. So instead of starting with nextToken(), your deserializer needs to start with currentToken(), and only use nextToken() for additional content.

Hope this helps.

Thanks, this solved my confusion!!!