以下是服务器响应的一部分:
Result
我创建了一个public class Result
{
private TObject[] result;
private boolean ok;
public void setOk (boolean ok) //Rest of the code
public void setResult (TObject[] result) //...
public TObject[] getResult () //...
public boolean getOk () //...
}
类,它类似于(Trimmed to reduce code):
Abstract Class
我有TObject
名为@JsonTypeInfo (use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes ({
@JsonSubTypes.Type (name = "chat", value = Chat.class),
@JsonSubTypes.Type (name = "message", value = Message.class),
@JsonSubTypes.Type (name = "message_entity", value = MessageEntity.class),
})
public abstract class TObject
{
int update_id;
boolean isUpdate;
public void setUpdate_id (int update_id)
{
this.update_id = update_id;
isUpdate = true;
}
public int getUpdate_id ()
{
return update_id;
}
}
:
@JsonTypeInfo (use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
问题是,因为我使用了
update_id
它没有将JsonTypeInfo.Id.NAME
识别为字段,而是将其识别为com.fasterxml.jackson.databind.JsonMappingException: Could not resolve type id 'update_id' into a subtype of [simple type, class org.telegram.objects.TObject]: known type ids = [TObject, chat, message, message_entity]
并向我显示:
update_id
现在请告诉我如何告诉杰克逊将TObject
解析为JsonTypeInfo.Id.NAME
字段并且不要将其混淆为<nav class="navbar navbar-default navbar-fixed-top">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Brand</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
<li><a href="#">Link</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">One more separated link</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Link</a></li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
?
答案 0 :(得分:1)
我会试着解释这里发生了什么。那么让我们来看看你的注释:
杰克逊希望Result
拥有这种格式。 { "ok": true, "result": []}
这部分是正确的。但TObject
已
@JsonTypeInfo (use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
JsonTypeInfo.As.WRAPPER_OBJECT
表示杰克逊会尝试在结果数组中找到{"chat":{}}
或{"message":{}}
或{"message_entity":{}}
。这是演示:
{ "ok": true, "result": [{"chat":{}}, {"message_entity":{}}, {"message":{}}]}
但是你在json中的第一个元素实际上是update_id
。杰克逊找不到任何update_id
类型,这就是为什么他只是停止解析并抛出异常。所以回答你的问题:how can I tell jackson to parse update_id as a field of TObject and don't confuse it as JsonTypeInfo.Id.NAME
:无法使用JsonTypeInfo ,因为jackson甚至不认为这部分来自TObject
。他将尝试在json中找到TObject
1层。如果你不能改变你的json,你必须完全重构你的类或创建自定义反序列化器。
我在这里制作了一个小型演示如何使用@JsonAnySetter
和@JsonAnyGetter
:https://gist.github.com/varren/766b6830878c9e15c51784f57b303646#file-jsonanygetter-and-jsonanysetter
此演示中的Update类的自定义JsonDeserializer
和JsonSerializer
也可以使用。 https://gist.github.com/varren/766b6830878c9e15c51784f57b303646#file-custom-deserializer-and-serializer
只需删除所有typeinfo注释并添加
即可private static class TObjectDeserializer extends JsonDeserializer<TObject> {
@Override
public TObject deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
JsonNode tree = p.readValueAsTree();
tree.get("chat");
TObject resultValue = null;
if(tree.has("chat")){
resultValue = p.getCodec().treeToValue(tree.get("chat"), Chat.class);
}else if(tree.has("message")){
resultValue = p.getCodec().treeToValue(tree.get("message"),Message.class);
} else if(tree.has("message_entity")){
resultValue = p.getCodec().treeToValue(tree.get("message_entity"),MessageEntity.class);
}
if(resultValue!= null)
resultValue.setUpdateId(tree.get("update_id").asInt());
return resultValue;
}
}
private static class TObjectSerializer extends JsonSerializer<TObject> {
private static ObjectMapper mapper = new ObjectMapper();
@Override
public void serialize(TObject value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeStartObject();
gen.writeNumberField("update_id", value.getUpdateId());
String key = "";
if(value instanceof Chat){
key = "chat";
}else if(value instanceof Message){
key = "message";
} else if(value instanceof MessageEntity){
key = "message_entity";
}
gen.writeFieldName(key);
gen.writeRawValue(mapper.writeValueAsString(value));
gen.writeEndObject();
}
}