简体   繁体   中英

Exception while parsing json string with jackson library

This is the json I'm trying to parse using Jackson Java library.
Its a Vector of BackgroundShape s.
BackgroundShape subclasses include:

  • BGRectangle
  • BGCircle

In this json snippet there is 2 BGRectangle s, but it may contain BGCircle s also, which have some different attributes to BGRectangle s.
So I want to parsing to be able to handle various class types within the json

{
    "bgShapes": [
        {
            "@class" : "com.code.test.BGRectangle",
            "position": {
                "x": -110.0,
                "y": -28.0,
                "z": -6.0
            },
            "angle": 0.0,
            "width": 10.0,
            "height": 10.0,
            "textureSelection": "NUKE"
        },
        {
            "@class" : "com.code.test.BGRectangle",
            "position": {
                "x": 10.0,
                "y": 8.0,
                "z": -6.0
            },
            "angle": 0.0,
            "width": 1.0,
            "height": 1.0,
            "textureSelection": "NUKE"
        }
    ]
}

Main.java

ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(org.jbox2d.common.Vec3.class.class, Vec3Mixin.class); 
Level zoo = mapper.readValue(new File("levels/level1.json"), Level.class);

Getting this exception at the moment:

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Could not find creator property with name 'position' (in class com.code.test.BackgroundShape)
 at [Source: levels/level1.json; line: 1, column: 1]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:584)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.addBeanProps(BeanDeserializerFactory.java:551)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:267)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:168)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:405)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:354)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:267)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:247)
    at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:146)
    at com.fasterxml.jackson.databind.DeserializationContext.findContextualValueDeserializer(DeserializationContext.java:305)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.createContextual(CollectionDeserializer.java:151)
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.createContextual(CollectionDeserializer.java:23)
    at com.fasterxml.jackson.databind.DeserializationContext.findContextualValueDeserializer(DeserializationContext.java:309)
    at com.fasterxml.jackson.databind.deser.impl.PropertyBasedCreator.construct(PropertyBasedCreator.java:96)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:414)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:298)
    at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:247)
    at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:146)
    at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:322)
    at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:2990)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2884)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1988)
    at com.code.test.Main.main(Main.java:16)

Level.java

@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS, include = As.PROPERTY, property = "@class")
public class Level {

    private Vector<BackgroundShape> bgShapes = new Vector<BackgroundShape>();

    @JsonCreator
    public Level(@JsonProperty("bgShapes") Vector<BackgroundShape> bgShapes) throws GLException, IOException {

        this.bgShapes = bgShapes;
        System.out.println("Level created");
    }
}

Shape.java

public abstract class Shape{

    @JsonProperty("textureSelection") protected String textureSelection;

    @JsonCreator
    public Shape(@JsonProperty("textureSelection") String textureSelection) {
        this.textureSelection = textureSelection;
    }
}

BackgroundShape.java

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = As.PROPERTY, property = "@class")
@JsonSubTypes({ 
    @JsonSubTypes.Type(value = BGRectangle.class, name = "BGRectangle"), 
    @JsonSubTypes.Type(value = BGCircle.class, name = "BGCircle") })
public abstract class BackgroundShape extends Shape {

    @JsonProperty("position") private Vec3 position;
    @JsonProperty("angle") private float angle;

    @JsonCreator
    public BackgroundShape(
            @JsonProperty("position") Vec3 position, 
            @JsonProperty("angle") float angle, 
            @JsonProperty("textureSelection") String textureSelection) {
        super(textureSelection);

        this.position = position;
        this.angle = angle;     
    }
}

BGRectangle.java

public class BGRectangle extends BackgroundShape{

    @JsonProperty("width") private float width;
    @JsonProperty("height") private float height;

    @JsonCreator
    public BGRectangle (
            @JsonProperty("position") Vec3 position, 
            @JsonProperty("angle") float angle, 
            @JsonProperty("width") float width, 
            @JsonProperty("height") float height, 
            @JsonProperty("textureSelection")String textureSelection) { 
        super(position, angle, textureSelection);

        this.width = width;
        this.height = height;
    };
}

EDIT: Added mixin abstract class to ObjectMapper ..

public abstract class Vec3Mixin {

    public Vec3Mixin(
            @JsonProperty("x") float x,
            @JsonProperty("y") float y, 
            @JsonProperty("z") float z) {
    }
}

I assume Vec3 is a third party class (possible from an OpenGL binding for Java library) which have a constructor like this:

public Vec3(float x, float y, float z) {
    // ...
}

When Jackson encounters this class during deserialization, she would like to instantiate it, but this class doesn't have no-arg constructor only the one with three parameters. Since parameter names are not available during runtime, Jackson is unable to determine which properties of the JSON should be assigned to which constructor parameter. To resolve this you would normally annotate the constructor parameters with @JSONProperty (as you did with other classes) but this class is not under your control.

Jackson Mixin Annotations can be used in this case to provide the necessary information to Jackson. First define a mixin abstract class:

public abstract class Vec3Mixin {

    public Vec3Mixin(@JsonProperty("x") float x, 
                     @JsonProperty("y") float y, 
                     @JsonProperty("z") float z) {
    }
}

Finally, the mixin class has to be associated with the original class:

ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(Vec3.class, Vec3Mixin.class);  
Level zoo = mapper.readValue(new File("levels/level1.json"), Level.class);

Just for the sake of completeness, this is the official documentation of the mix-in feature: http://wiki.fasterxml.com/JacksonMixInAnnotations (but not working as of this writing).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM