JAXB序列化JsonElement场POJO
我有一个POJO类,如:JAXB序列化JsonElement场POJO
class Cat {
public Cat() {}
private String name;
private JsonElement arbitraryProperties;
}
我使用杰克逊(JAXB)和cat
是一个资源我要导入和导出。
GET /cats/{id}
POST /cats
导出工作正常。导入不起作用,因为JsonElement
是抽象的。所以我将@JsonDeserialize(使用= MyJsonElementDeserialize.class)注释添加到arbitraryProperties field
。
的MyJsonElementDeserialize
类的样子:
public class JsonElementDeserialize extends JsonDeserializer<JsonElement> {
public JsonElementDeserialize() {
}
@Override
public JsonElement deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
return new JsonObject(); // here I need to create my object later
}
}
当我现在请与有效载荷POST /猫:
{
"name": "Mia",
"arbitraryProperties": {
"a": 3,
"b": [],
"c": {
"d": "race"
}
}
}
杰克逊返回错误代码400:
无法识别的字段“a” (Cat类),未标记为可忽略的(1个已知属性:“name”])。
我的错误在哪里?我如何在我的POJO中有一个JsonElement
自动序列化和反序列化?
下面是使用Cat
setter方法改造的东西杰克逊解析(如Map<String, Object>
)到GSON JsonElement
类型的简单解决方案:
void setArbitraryProperties(Map<String, Object> properties) {
arbitraryProperties = new Gson().toJsonTree(properties).getAsJsonObject();
}
你可以,如果你可以”做类似的事情自定义解串器内在这里使用setter。我发现setter/getters更容易与Jackson进行转换。
请注意,Gson
实例可用于将Map
转换为JsonElement
(实际上为JsonObject
)。 Docs for toJsonTree。
既然你有一个在GSON中定义的类型的字段,因此你有GSON作为依赖并且无情地需要GSON来创建这个字段,你可以考虑Sharon的建议并跳过Jackson并使用GSON进行反序列化。
我认为这是处理无法识别的字段的最好方法。甚至可以使用Map作为字段类型而不是JsonElement。 –
如果您使用Spring mvc,请尝试在控制器方法中使用“produce = MediaType.APPLICATION_JSON_VALUE”和@ResponseBody。
这里的问题是,反序列化器必须消耗它们覆盖的所有内容:也就是说,如果反序列化器不“读取”将绑定的JSON内容(这里的内容为a
),它们将留作进一步处理。
解决方案应该是简单的,只需要调用
jsonParser.skipChildren();
在deserialize
方法,它会跳过当前输入令牌,以及它的所有内容(如果它的JSON对象或阵列)。
另外,如果你想使用的内容,你可以使用
jsonParser.readValueAsTree();
,并有一些其他方便的方法。
如果可以,我会将JsonElement更改为JsonNode,并使用Jackson的“树模型”。
什么是JsonElement?它是GSON的一部分吗?所以为什么不使用它? –
是JsonElement是来自GSON的抽象类。 https://google.github.io/gson/apidocs/com/google/gson/JsonElement.html – user1482309
一个小的建议:标题说“序列化”,但问题是关于“反序列化”。改变标题会更有意义,更容易以这种方式找到相关问题。 – StaxMan