使用杰克逊将不同类型的沙漠化为单个场地



我有一个下面的类,我想用来反序列化JSON

public interface MyObject {
@JsonProperty("prop")
String prop;
@JsonProperty("value")
Double value();        // Need this to be either a double or a string or a Map
}

然而,我希望能够用双值解析这两个JSON

{
prop: "myprop",
value: 15.7
}

和具有非Double值的JSON,如字符串或映射

{
prop: "myprop1",
value: {
"attr1": "value1",
"attr2": 12.0
}
}

我查看了@JsonSubTypes注释,但这似乎只对涉及继承的情况有用。在杰克逊有可能做到这一点吗?如果是这样,我如何定义我的Java类来实现同样的目的?

通常,我不鼓励使用任意类型的数据点。如果你愿意的话,拥有强大的类型会带来很多好处。然而,由于您只讨论了反序列化,因此可能只是在阅读其他人生成的JSON。

解决方案非常简单:使用Object字段。

public static class MyObject {
@JsonProperty("prop")
String prop;
@JsonProperty("value")
Object value;        // <- object
}
@Test
public void testUnknownType() throws JsonProcessingException {
final ObjectMapper objectMapper = new ObjectMapper();
final MyObject object1 = objectMapper.readValue("{n" +
"  "prop": "myprop",n" +
"  "value": 15.7n" +
"}", MyObject.class);
Assert.assertEquals(15.7d, object1.value);
final MyObject object2 = objectMapper.readValue("{n" +
"  "prop": "myprop1",n" +
"  "value": {n" +
"    "attr1": "value1",n" +
"    "attr2": 12.0n" +
"  }n" +
"}", MyObject.class);
Assert.assertTrue(object2.value instanceof Map);
}

你可以做的是这样的事情:

@JsonDeserialize(using = ExampleDeserializer.class)
public class Example{
String prod;
Object value; /*this field will takes multiple types*/
}

ExampleDeserializer将是这样的:

public class ExampleDeserializer extends StdDeserializer<Example> {
public ExampleDeserializer() {
super(Example.class);
}
public ExampleDeserializer(Class<?> vc) {
super(vc);
}
@Override
public Example deserialize(JsonParser p, DeserializationContext ctx) throws IOException {
Example ex = new Example();
ObjectCodec mapper = p.getCodec();
if (mapper == null) mapper = new ObjectMapper();
JsonNode tree = mapper.readTree(p);
JsonNode internalNode;
if (tree.get("prod") != null) {
internalNode = tree.get("prod");
prop = internalNode.get("prod").asText();
}
if (tree.get("value") != null) {
internalNode = tree.get("value");
value = (Double) internalNode.get("value").asDouble() or asText()...;
}
}

如果将不同的类型作为不同的名称,那么事情会稍微容易一些,所以在JSON中应该是:

{
prop: "my_map_prop",
mapvalue: {
"attr1": "value1",
"attr2": 12.0
}
}

{
prop: "my_string_prop",
stringvalue: "string"
}

如果你这样做,那么你就有更多的工具可以用来强制执行有效性。

最新更新