繁体   English   中英

用杰克逊库解析json字符串时发生异常

[英]Exception while parsing json string with jackson library

这是我尝试使用Jackson Java库解析的json
它是BackgroundShape s的Vector
BackgroundShape子类包括:

  • BGRectangle
  • BGCircle

在这个json片段中,有2个BGRectangle ,但也可能包含BGCircle ,它们与BGRectangle的属性不同。
所以我想解析以便能够处理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);

现在得到这个异常:

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;
    };
}

编辑:添加了mixin抽象类到ObjectMapper ..

public abstract class Vec3Mixin {

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

我假设Vec3是第三方类(可能来自Java库的OpenGL绑定),具有以下构造函数:

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

当杰克逊在反序列化过程中遇到此类时,她想实例化它,但是此类仅具有三个参数的类就没有noarg构造函数。 由于参数名称在运行时不可用,因此Jackson无法确定应将JSON的哪些属性分配给哪个构造函数参数。 要解决此问题,通常可以使用@JSONProperty注释构造函数参数(就像对其他类所做的那样),但是此类不受您控制。

在这种情况下,可以使用Jackson Mixin注释向Jackson提供必要的信息。 首先定义一个mixin抽象类:

public abstract class Vec3Mixin {

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

最后,mixin类必须与原始类相关联:

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

为了完整起见,这是混合功能的正式文档: http : //wiki.fasterxml.com/JacksonMixInAnnotations (但在撰写本文时不起作用)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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