我有以下JSON:
{
"animals": {
"113110": {
"id": 113110,
"name": "Dog",
.....
},
"121853": {
"id": 121853,
"name": "Cat",
.....
}
}
}
理想情况下,JSON应如下所示,实施杰克逊注释将是微不足道的:
{
"animals": [
{
"id": 113110,
"name": "Dog",
.....
},
{
"id": 121853,
"name": "Cat",
.....
}
]
}
但是,有没有办法使用Jackson来抽象对象名称,这样我就可以使用原始的JSON,如果有人知道我的意思?
编辑:
我不知道如何创建我的POJO。我可以用对象113110和121853创建一个Animal类,但由于这些对象总是不同,我如何在我的Animal类中使用Jackson注释以便我可以反序列化JSON?
答案 0 :(得分:3)
谢谢大家,但我真的不能理解其余的答案(我真的不想深入研究杰克逊,我只是想把它转换为POJO),所以我找到了另一种解决方案。
我遗漏了一些关键信息:我发布的JSON是一个更大的JSON对象的一部分。
我最终使用了Jackson的@AnySetter,因为我注意到任何与“animals”相关的“不可解析”的JSON数据都可以在其父类中定义如下的additionalProperties中检索:
public class AnimalParent {
@JsonIgnore
private Animal animal;
@JsonIgnore
private Map<String, Object> additionalProperties =
new HashMap<String, Object>();
public Animal getAnimal() {
return this.animal;
}
public void setAnimal(Animal animal) {
this.animal = animal;
}
@JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
@JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
然后在我解析父JSON的main方法中,在完成解析后解析动物后我有以下内容。
// start parsing parent JSON
...
// end parsing parent JSON
// parse animal
ObjectMapper mapper = new ObjectMapper();
if (animalParent.getAdditionalProperties() != null) {
for (Map.Entry<String, Object> item : animalParent
.getAdditionalProperties().entrySet()) {
Animal animal = mapper.convertValue(item.getValue(), Animal.class);
animalParent.setAnimal(animal);
}
答案 1 :(得分:1)
就个人而言,只要我处理不易映射到POJO的怪异JSON,我就会进行自定义序列化。
我可能会让POJO看起来像这样:
public class Animal
{
String id;
String name;
}
public class JsonThing
{
List<Animal> animals;
}
然后我将使用Jackson stream API实现自定义解析器。这是JsonDeserializer<JsonThing>
的快速存根:
public Stuff deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
.... // Start by creating a JsonThing instance and init the list.
while (jp.nextToken() != JsonToken.END_OBJECT)
{
jp.nextToken();
switch (jp.getCurrentName())
{
case "animals":
jp.nextToken(); // Skip to {
jp.nextToken(); // Skip id field
Animal a = jp.readValuesAs(Animal.class);
// Add to list
}
}
..... // Return JsonThing
}
答案 2 :(得分:1)
如果事先不知道密钥,请使用地图代替POJO。
你可以尝试任何一个。
示例代码:(使用 Jackson Library )
TypeReference<Map<String, Object>> typeRef = new TypeReference<Map<String, Object>>() {};
ObjectMapper mapper = new ObjectMapper();
try {
Map<String, Object> data = mapper.readValue(jsonString, typeRef);
} catch (Exception e) {
System.out.println("There might be some issue with the JSON string");
}
示例代码:使用GSON Library
Type type = new TypeToken<Map<String, Object>>() {}.getType();
Map<String, Object> data = new Gson().fromJson(jsonString, type);
答案 3 :(得分:1)
根据OP示例,当您的JSON是“动态”时总是有点乱。主要方法是
Map
- 结构JsonNode
)所有这些方法都有缺点。 Map
- 方法不提供类型安全性,并且在遍历对象结构时不提供太多功能。
JsonNode
方法提供了一些不错的类型方法和一些遍历方法。 IMO这是一种比Map
方法更清晰的方法。
POJO方法是类型安全的,但是需要自定义反序列化器,这通常不太漂亮......
因此,也许可以使用以下“混合”方法。
// Setup the mapper
final ObjectMapper mapper = new ObjectMapper();
// Parse the json to a tree (JsonNode). This is IMO nicer than the
// Map since it exposes some nice methods for managing the
// underlying data
final JsonNode json = mapper.readTree(jsonString);
// Alt 1, use JsonNode directly
for (final JsonNode animal : json.path("animals")) {
final int id = animal.get("id").asInt();
final String name = animal.get("name").asText();
// Do stuff with name and id...
}
如果JsonNode
方法感觉有点 raw ,则可以在不使用反序列化器的情况下将JsonNode
对象转换为POJO。如果你假设以下POJO:
public class Animal {
private final int id;
private final String name;
@JsonCreator
public Animal(@JsonProperty("id") final int id, @JsonProperty("name") final String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
}
然后,此代码可用于转换为POJO:
final ObjectMapper mapper = new ObjectMapper();
final JsonNode json = mapper.readTree(jsonString);
// Alt 2, convert to a Pojo
for (final JsonNode animal : json.path("animals")) {
final Animal a = mapper.treeToValue(animal, Animal.class);
// Handle the animal instance...
}
最后,如果POJO仍然包含动态数据,您可以使用以下方法来处理它。在您的POJO中,声明以下内容:
private final Map<String, Object> dynamic = new HashMap<>();
@JsonAnySetter
private void set(String name, Object value) {
dynamic.put(name, value);
}
请注意,该方法不一定是public
(即它可以从外部世界隐藏)。通过这种方式,您将获得所有未知/动态JSON元素。
答案 4 :(得分:0)
或许这只是将简单的Map
与pojos结合起来的问题?像:
public class Wrapper {
public Map<Long, Animal> animals;
}
public class Animal {
public long id;
public String name;
}
就是这样;虽然有匹配的ids,但也许没有必要尝试模拟这种依赖。