jackson json 嵌套对象_Jackson JSON在嵌套类的集合上给出了异常

Jackson JSON has no problem serializing/deserializing this class:

public class MyClass {

public class Nested {

public String string;

public Nested() {}

}

public Nested nestedVar;

}

but on this one:

public class MyClass {

class Nested {

public String string;

public Nested() {}

}

public Nested nestedVar;

public List nestedList;

}

I get this exception when deserializing:

com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class test.MyClass$Nested]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)

at [Source: java.io.StringReader@26653222; line: 1, column: 48] (through reference chain: test.MyClass["nestedList"]->java.util.ArrayList[0])

In the first case, Jackson has no problem dealing with an instance of a nested class, but not in the second case.

Must I write a custom deserializer?

Test code (Jackson 2.6.3):

import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;

import java.io.StringReader;

import java.io.StringWriter;

import java.util.ArrayList;

import java.util.List;

public class ATest {

public static void main(String[] args) throws IOException {

ObjectMapper mapper = new ObjectMapper();

StringWriter sw = new StringWriter();

MyClass myClass = new MyClass();

MyClass.Nested nestedVar = myClass.new Nested();

List nestedList = new ArrayList<>();

nestedList.add(nestedVar);

myClass.nestedList =nestedList;

myClass.nestedVar = nestedVar;

mapper.writeValue(sw, myClass);

System.out.println(sw.toString());

StringReader sr = new StringReader(sw.toString());

MyClass z = mapper.readValue(sr, MyClass.class);

}

}

解决方案

Looks like the recognition of non-static inner classes is done where they are properties directly on their containing bean (BeanDeserializerBase.java line 476 in 2.6.3). So an intervening Collection deserializer would go past that. A custom deserializer is likely the simplest option here.

Note that you can still use Jackson to read the properties of Nested, and just implement the construction of it yourself, in a custom deserializer only used when deserializing a list of Nested objects.

To do this, annotate the list like so:

@JsonDeserialize(contentUsing = NestedDeserializer.class)

public List nestedList;

and then use a custom deserializer that will:

Look at the parsing context when called to find the containing MyClass instance.

Encapsulate a default/root-level deserializer of Nested to delegate the work of deserializing the content to.

For example:

public static final class NestedDeserializer extends StdDeserializer

implements ResolvableDeserializer {

private JsonDeserializer underlyingDeserializer;

public NestedDeserializer() {

super(MyClass.Nested.class);

}

@Override

public void resolve(DeserializationContext ctxt) throws JsonMappingException {

underlyingDeserializer = ctxt

.findRootValueDeserializer(ctxt.getTypeFactory().constructType(MyClass.Nested.class));

}

@Override

public Nested deserialize(JsonParser p, DeserializationContext ctxt)

throws IOException, JsonProcessingException {

JsonStreamContext ourContext = p.getParsingContext();

JsonStreamContext listContext = ourContext.getParent();

JsonStreamContext containerContext = listContext.getParent();

MyClass container = (MyClass) containerContext.getCurrentValue();

MyClass.Nested value = container.new Nested();

// note use of three-argument deserialize method to specify instance to populate

underlyingDeserializer.deserialize(p, ctxt, value);

return value;

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值