使用Jackson库对JSON进行初始化

dgjrabp2  于 5个月前  发布在  其他
关注(0)|答案(1)|浏览(74)
"result" : {
    "id" : "123", 
    "category" : "typeA",
    "value" : {
        "typeAField" : "123"
    }
}

"result" : {
    "id" : "321", 
    "category" : "typeB",
    "value" : {
        "typeBAField1" : "123",
        "typeBAField2" : true
    }
}

字符串
我想把这样的json结构改成java对象,结果有id、category和value,value中对象的类型根据category而变化。
所以我创建了这样的对象:当类别的值是typeA时,我想使用TypeA.java对象,当类别的值是typeB时,我想使用TypeB.java对象。

public class Result { 
  String id;
  String category;
  Values value;
}

public abstract class Values {
    
}

public TypeA extends Values {
    String typeAField;
}

public TypeB extends Values {
    String typeBField1;
    String typeBField2;
}


输入如下:

"result" : {
    "id" : "123", 
    "category" : "typeA",
    "value" : {
        "typeAField" : "123"
    }
}


当输入文本时,我想编写代码将其转换为Result.java对象。

第一种方法

@Data
class Result {
    private String id;
    private String category;
    private Values value;
}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT, property = "category")
@JsonSubTypes({
        @JsonSubTypes.Type(value = TypeA.class, name = "typeA"),
        @JsonSubTypes.Type(value = TypeB.class, name = "typeB")
})
abstract class Values {}

@Data
class TypeA extends Values {
    private String typeAField;
}

@Data
class TypeB extends Values {
    private String typeBAField1;
    private boolean typeBAField2;
}

String json1 = "{\"id\":\"123\",\"category\":\"typeA\",\"value\":{\"typeAField\":\"123\"}}";
String json2 = "{\"id\":\"321\",\"category\":\"typeB\",\"value\":{\"typeBAField1\":\"123\",\"typeBAField2\":true}}";

ObjectMapper objectMapper = new ObjectMapper();

Result result1 = objectMapper.readValue(json1, Result.class); // error 
Result result2 = objectMapper.readValue(json2, Result.class);

错误详情

com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve type id 'typeAField' as a subtype of `Values`: known type ids = [typeA, typeB] (for POJO property 'value')
 at [Source: (String)"{"id":"123","category":"typeA","value":{"typeAField":"123"}}"; line: 1, column: 41] (through reference chain: Result["value"])

我尝试的第二种方法

@Data
class Result {
    private String id;
    private String category;
    private Values value;

    @JsonSetter("value")
    public void setValue(Map<String, Object> valueMap) {
        ObjectMapper objectMapper = new ObjectMapper();

        try {
            if (valueMap.containsKey("typeAField")) {
                this.value = objectMapper.convertValue(valueMap, TypeA.class);
            }
            else {
                this.value = objectMapper.convertValue(valueMap, TypeB.class);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

abstract class Values {}

@Data
class TypeA extends Values {
    private String typeAField;
}

@Data
class TypeB extends Values {
    private String typeBAField1;
    private boolean typeBAField2;
}


它的工作,但setter部分似乎不干净。有什么更好的方法吗?我缺乏很多,但我想得到帮助提前谢谢你

ukdjmx9f

ukdjmx9f1#

在第一个方法中,您使用JsonTypeInfo.As.WRAPPER_OBJECT,如果JSON数据是这样的,它将工作:

{
    "result": {
        "id": "321",
        "category": "typeB",
        "value": {
            "typeB": {
                "typeBAField1": "123",
                "typeBAField2": true
            }
        }
    }
}

字符串
现在,您可以使用JsonTypeInfo.As.EXTERNAL_PROPERTY,它只能用于属性,而不是根据JavaBean的类型(类)。
public static final JsonTypeInfo.As EXTERNAL_PROPERTY
包含机制类似于PROPERTY,不同之处在于属性在层次结构中高出一级,即作为与JSON Object相同级别的兄弟属性包含到类型中。请注意,此选项只能用于属性,而不能用于类型(类)。尝试将其用于类将导致基本PROPERTY的包含策略
所以你必须使用JsonTypeInfo.As.EXTERNAL_PROPERTY注解Result类的value属性,并删除抽象的Values类注解。然后你就可以无错误地对JSON数据进行格式化。

@Data
public class Result {
    private String id;
    private String category;
    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "category")
    @JsonSubTypes({
            @JsonSubTypes.Type(value = TypeA.class, name = "typeA"),
            @JsonSubTypes.Type(value = TypeB.class, name = "typeB")
    })
    private Values value;
}

abstract class Values {}

相关问题