java CustomDeserializer 没有默认(无参数)构造函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43214545/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
CustomDeserializer has no default (no arg) constructor
提问by abril
I am consuming a REST Api with RestTemplate. The response I'm getting from the API has lots of nested objects. Here's a little snippet as an example:
我正在使用 RestTemplate 使用 REST Api。我从 API 得到的响应有很多嵌套对象。这里有一个小片段作为例子:
"formularios": [
{
"form_data_id": "123006",
"form_data": {
"form_data_id": "123006",
"form_id": "111",
"efs": {
"1": {},
"2": "{\"t\":\"c\",\"st\":\"m\",\"v\":[{\"id\":\"3675\",\"l\":\"a) Just an example\",\"v\":\"1\"},{\"id\":\"3676\",\"l\":\"b) Another example.\",\"v\":\"2\"}]}"
}
}
The problem I'm having is that most of the times the "1" actually has content, just like "2", and the Hymanson just parses it as a String on the object "efs". But sometimes, just like in the code snippet, the API sends it empty, and Hymanson takes it as an Object, which gives me an error that says something about START_OBJECT (can't remember the exact error, but it's not important for this question).
我遇到的问题是,大多数时候“1”实际上有内容,就像“2”一样,Hymanson 只是将它解析为对象“efs”上的字符串。但有时,就像在代码片段中一样,API 将其发送为空,而 Hymanson 将其作为一个对象,这给了我一个错误,说明了 START_OBJECT(不记得确切的错误,但对于这个问题并不重要) )。
So I decided to make a custom deserializer so when Hymanson reads "1", it ignores the empty object and just parses it as a null string.
所以我决定制作一个自定义反序列化器,这样当 Hymanson 读取“1”时,它会忽略空对象并将其解析为空字符串。
Here's my custom deserializer:
这是我的自定义解串器:
public class CustomDeserializer extends StdDeserializer<Efs> {
public CustomDeserializer(Class<Efs> t) {
super(t);
}
@Override
public Efs deserialize(JsonParser jp, DeserializationContext dc)
throws IOException, JsonProcessingException {
String string1 = null;
String string2 = null;
JsonToken currentToken = null;
while ((currentToken = jp.nextValue()) != null) {
if (currentToken.equals(JsonToken.VALUE_STRING)) {
if (jp.getCurrentName().equals("1")) {
string1 = jp.getValueAsString();
} else {
string2 = jp.getValueAsString();
}
} else {
if (jp.getCurrentName().equals("2")) {
string2 = jp.getValueAsString();
}
}
}
return new Efs(string1, string2);
}
}
And this is the way I'm using it when receiving the response from the API:
这就是我在从 API 接收响应时使用它的方式:
ObjectMapper mapper = new ObjectMapper();
SimpleModule mod = new SimpleModule("EfsModule");
mod.addDeserializer(Efs.class, new CustomDeserializer(Efs.class));
mapper.registerModule(mod);
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
MappingHymanson2HttpMessageConverter jsonMessageConverter = new MappingHymanson2HttpMessageConverter();
jsonMessageConverter.setObjectMapper(mapper);
messageConverters.add(jsonMessageConverter);
RestTemplate restTemplate = new RestTemplate();
restTemplate.setMessageConverters(messageConverters);
I'm getting the error:
我收到错误:
CustomDeserializer has no default (no arg) constructor
But I don't know exactly what I'm doing wrong nor how to solve it. Thanks for the help and apologies for the long question, I wanted to give as much context as possible.
但我不知道我做错了什么,也不知道如何解决。感谢您对这么长的问题的帮助和道歉,我想提供尽可能多的背景信息。
采纳答案by Doron Yakovlev-Golani
It is required that you have a default constructor without arguments. What you can do is create one (or replace the other one if you don't really need it):
要求您有一个不带参数的默认构造函数。您可以做的是创建一个(如果您真的不需要,则替换另一个):
public class CustomDeserializer extends StdDeserializer<Efs> {
public CustomDeserializer() {
super(Efs.class);
}
...
}
回答by Edgar Asatryan
There is also one trap that users can fall into (like my self). If you declare deserializer as a inner class (not a static nested class) like:
还有一个用户可能会陷入的陷阱(比如我自己)。如果您将反序列化器声明为内部类(不是静态嵌套类),例如:
@JsonDeserialize(using = DomainObjectDeserializer.class)
public class DomainObject {
private String key;
public class DomainObjectDeserializer extends StdDeserializer<DomainObject> {
public DomainObjectDeserializer() {
super(DomainObject.class);
}
@Override
public DomainObject deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
// code
}
}
}
Hymanson uses the Class#getDeclaredConstructor()with no argument (method accepts vararg
) witch means: give me a default (no argument) constructor. Code above will throw exception when Hymanson tries to create DomainObjectDeserializer
because javac
does generate the constructor that does accept enclosing class reference. Technically speaking DomainObjectDeserializer
does not have a default constructor.
Hymanson 使用Class#getDeclaredConstructor()没有参数(方法接受vararg
)女巫的意思是:给我一个默认(无参数)构造函数。当 Hymanson 尝试创建时,上面的代码将抛出异常,DomainObjectDeserializer
因为javac
确实生成了接受封闭类引用的构造函数。从技术上讲 DomainObjectDeserializer
,没有默认构造函数。
For a curiosity sake you can execute DomainObjectDeserializer.class.getDeclaredConstructors()
and ensure that method does return single element array containing constructor definition with enclosing class reference.
出于好奇,您可以执行DomainObjectDeserializer.class.getDeclaredConstructors()
并确保该方法确实返回包含带有封闭类引用的构造函数定义的单元素数组。
The DomainObjectDeserializer
should be declared as a static
class.
本DomainObjectDeserializer
应被宣布为一个static
类。
Here is a good answerto read in more details.
这是一个很好的答案,可以详细阅读。