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自动序列化和反序列化?

+1

什么是JsonElement?它是GSON的一部分吗?所以为什么不使用它? –

+0

是JsonElement是来自GSON的抽象类。 https://google.github.io/gson/apidocs/com/google/gson/JsonElement.html – user1482309

+0

一个小的建议:标题说“序列化”,但问题是关于“反序列化”。改变标题会更有意义,更容易以这种方式找到相关问题。 – StaxMan

下面是使用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进行反序列化。

+2

我认为这是处理无法识别的字段的最好方法。甚至可以使用Map作为字段类型而不是JsonElement。 –

如果您使用Spring mvc,请尝试在控制器方法中使用“produce = MediaType.APPLICATION_JSON_VALUE”和@ResponseBody。

这里的问题是,反序列化器必须消耗它们覆盖的所有内容:也就是说,如果反序列化器不“读取”将绑定的JSON内容(这里的内容为a),它们将留作进一步处理。

解决方案应该是简单的,只需要调用

jsonParser.skipChildren(); 

deserialize方法,它会跳过当前输入令牌,以及它的所有内容(如果它的JSON对象或阵列)。

另外,如果你想使用的内容,你可以使用

jsonParser.readValueAsTree(); 

,并有一些其他方便的方法。

如果可以,我会将JsonElement更改为JsonNode,并使用Jackson的“树模型”。