使用 Jackson 将不同类型反序列化为单个字段
Deserialising different types to single field using Jackson
我有一个 class 想要用于反序列化 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
}
和具有非双精度值的 JSON,如字符串或映射
{
prop: "myprop1",
value: {
"attr1": "value1",
"attr2": 12.0
}
}
我查看了 @JsonSubTypes
注释,但它看起来只对涉及继承的情况有用。有可能在杰克逊做到吗?如果是这样,我如何定义我的 Java class 来实现同样的目标?
一般来说,我不鼓励使用任意类型的数据点。拥有强类型会带来很多好处,如果你愿意的话,我可以谈谈。但是,由于您只谈到了反序列化,因此您可能只是在阅读其他人制作的 JSON。
解决方法很简单:使用对象字段。
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.7\n" +
"}", MyObject.class);
Assert.assertEquals(15.7d, object1.value);
final MyObject object2 = objectMapper.readValue("{\n" +
" \"prop\": \"myprop1\",\n" +
" \"value\": {\n" +
" \"attr1\": \"value1\",\n" +
" \"attr2\": 12.0\n" +
" }\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"
}
如果您这样做,您就可以使用更多工具来执行有效性。
我有一个 class 想要用于反序列化 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
}
和具有非双精度值的 JSON,如字符串或映射
{
prop: "myprop1",
value: {
"attr1": "value1",
"attr2": 12.0
}
}
我查看了 @JsonSubTypes
注释,但它看起来只对涉及继承的情况有用。有可能在杰克逊做到吗?如果是这样,我如何定义我的 Java class 来实现同样的目标?
一般来说,我不鼓励使用任意类型的数据点。拥有强类型会带来很多好处,如果你愿意的话,我可以谈谈。但是,由于您只谈到了反序列化,因此您可能只是在阅读其他人制作的 JSON。
解决方法很简单:使用对象字段。
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.7\n" +
"}", MyObject.class);
Assert.assertEquals(15.7d, object1.value);
final MyObject object2 = objectMapper.readValue("{\n" +
" \"prop\": \"myprop1\",\n" +
" \"value\": {\n" +
" \"attr1\": \"value1\",\n" +
" \"attr2\": 12.0\n" +
" }\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"
}
如果您这样做,您就可以使用更多工具来执行有效性。