JAXB序列化POJO中的JsonElement字段

时间:2017-05-29 09:18:17

标签: java json serialization jaxb jackson

我有一个POJO类,如:

class Cat {
  public Cat() {}
  private String name;
  private JsonElement arbitraryProperties;
}

我正在使用Jackson(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 / cats时:

{
  "name": "Mia",
  "arbitraryProperties": {
        "a": 3,
        "b": [],
        "c": {
            "d": "race"
        }
   }
 }

Jacksons返回错误代码400:

  

无法识别的字段“a”(类Cat),未标记为可忽略(1个已知属性:“name”])。

我的错误在哪里?如何在我的POJO中有JsonElement自动序列化和反序列化?

4 个答案:

答案 0 :(得分:4)

这是一个简单的解决方案,使用Cat中的setter方法将Jackson解析的内容(例如Map<String, Object>)转换为GSON JsonElement类型:

void setArbitraryProperties(Map<String, Object> properties) {
    arbitraryProperties = new Gson().toJsonTree(properties).getAsJsonObject();
}

如果你不能在这里使用setter,你可以在自定义反序列化器中做类似的事情。我发现杰克逊的转换器更容易使用setter / getters。

请注意,Gson实例用于将Map转换为JsonElement(实际为JsonObject)。 toJsonTree的文档。

由于您在GSON中定义了一个类型的字段,因此您将GSON作为依赖项并且无情地需要GSON来创建此字段,您可以考虑Sharon的建议并跳过Jackson并使用GSON进行反序列化。

答案 1 :(得分:1)

这里的问题是反序列化器必须消耗它们所涵盖的所有内容:也就是说,如果你的反序列化器没有&#34;读取&#34;将绑定的JSON内容(此处为a的内容),留待进一步处理。

解决方案应该很简单,只需调用

即可
jsonParser.skipChildren();
deserialize方法中

它将跳过当前输入标记及其所有内容(如果它的JSON对象或数组)。

或者,如果您想使用内容,可以使用

jsonParser.readValueAsTree();

还有其他一些便利方法。

答案 2 :(得分:1)

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

答案 3 :(得分:0)

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