【问题标题】:How to represent sub-documents in JSON array as Java Collection using Jackson?如何使用 Jackson 将 JSON 数组中的子文档表示为 Java 集合?
【发布时间】:2014-09-01 22:35:33
【问题描述】:

如果能帮助我了解使用 Jackson Annotations 将我们从 Salesforce 收到的以下 JSON 响应反序列化为 Java 对象的最佳方法,我将不胜感激。

"records": [
  {
      "attributes": {
        "type": "Lead",
        "url": "/services/data/v30.0/sobjects/Lead/00Qi000000Jr44XEAR"
      },
      "Id": "00Qi000000Jr44XEAR",
      "Name": "Kristen Akin",
      "Address": {
          "city": null,
          "country": "USA",
          "state": "CA",
          "stateCode": null,
          "street": null
      },
      "Phone": "(434) 369-3100",
  },
  {
      "attributes": {
      "type": "Lead",
      "url": "/services/data/v30.0/sobjects/Lead/00Qi000000Jugv2EAB"
      },
      "Id": "00Qi000000Jugv2EAB",
      "Name": "Sarah Jones",
      "Address": {
        "city": null,
        "country": null,
        "state": "CA",
        "stateCode": null,
        "street": null
      },
      "Phone": "(408) 338-6066",
  }
]}

上面的 JSON 响应是一个包含 2 个元素的数组。我想将此 JSON 结构表示为使用 Jackson 的 Java 集合,例如:

@JsonProperty("records")
ArrayList<LinkedHashMap<?, ?>> recordList

上述对象表示反序列化 JSON 响应并表示为 HashMap 中的键值对,但问题是表示“属性”和“地址”子文档。在上面的 HashMap 中,它们的值被表示为相应的 JSON 子文档,而我更希望将 Attributes 子文档映射到 Attribute 对象,并且类似地,将 Address 子文档映射到 HashMap 中的 Address 对象,例如:

Key            Value
attributes     <Attributes> object
Id             00Qi000000Jr44XEAR
.....
Address        <Address> object
Phone          (434) 369-3100

在进行了一些 Google 搜索后,我想我可能必须使用 @JsonTypeInfo 和 @JsonSubTypes 属性,正如 link 中提到的那样。

但是,我不知道如何在这个特定场景中使用这些注释。感谢您对此的任何帮助。

【问题讨论】:

  • LinkedHashMap 中的 Key 和 Value 的类型是什么
  • 键为字符串,值为对象
  • AttributesAddress 是您的自定义类吗?
  • 是的,AttributesAddress 是我的自定义类。

标签: java json jackson deserialization


【解决方案1】:

如果您的 JSON 输入的结构是完全动态的,您可以将其读取为 JsonNode 甚至 Map。请参阅此link 了解更多信息。

如果你想将你的 JSON 映射到 java 类,但你不知道编译类型的所有属性,你可以利用the @JsonAnyGetter/@JsonAnySetter annotations。这是一个基于 JSON 的示例,它将 Address 类的未知属性存储在内部映射中。

public class JacksonMapping {
    public static final String JSON = "...";

    public static class Attributes {
        public String type;
        public URI url;
    }

    public static class Address {
        public String city;
        public String country;
        public String state;
        public Integer stateCode;
        public String street;
        private final Map<String, Object> otherAttributes = new HashMap<>();

        @JsonAnySetter
        public void setProperty(String name, Object value) {
            otherAttributes.put(name, value);
        }

        @JsonAnyGetter
        public Map<String, Object> getOtherAttributes() {
            return otherAttributes;
        }
    }

    public static class Record {
        @JsonProperty("Id")
        public String id;
        @JsonProperty("Name")
        public String name;
        public Attributes attributes;
        @JsonProperty("Address")
        public Address address;
        @JsonProperty("Phone")
        public String phone;
    }

    public static class RecordList {
        public List<Record> records;
    }

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        RecordList recordList = mapper.readValue(JSON, RecordList.class);
        System.out.println(mapper.writerWithDefaultPrettyPrinter()
                .writeValueAsString(recordList));
    }

}

我还可以尝试在工具的帮助下从您的 JSON 生成 java 对象。比如这个:http://www.jsonschema2pojo.org

【讨论】:

  • 感谢 Alexey 的回复。如果我们从 Salesforce 收到的字段是静态的,您建议的解决方案将起作用。为简单起见,我刚刚发布了基本字段,但实际上它们会更多,并且可能会因 Salesforce 提供大量自定义而因客户而异。因此,我想避免在类中创建特定字段,就好像我们有一个客户有一些新字段,那么我必须更改类结构。这就是为什么我想将它们添加到 HashMap 中,其中 Attributes 和 Address 子文档被映射到相应的自定义对象。希望对您有所帮助。
  • 谢谢阿列克谢。这就是我一直在寻找的。我接受了你的回答。
猜你喜欢
  • 2016-07-05
  • 1970-01-01
  • 1970-01-01
  • 2016-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多