首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Jackson在同一个文件中使用多个具有未知密钥名的JSON对象

使用Jackson在同一个文件中使用多个具有未知密钥名的JSON对象
EN

Stack Overflow用户
提问于 2015-05-07 23:24:21
回答 1查看 6.7K关注 0票数 4

为处理实体建筑物的应用程序构建模型。

理想情况下,我们会想要这样的东西:

城市有多个办公室,有多个房间,有房产。

我们使用jackson解析从API数据源接收到的JSON有效负载,结果与我看到的示例略有不同。

我们得到的格式是:

代码语言:javascript
复制
{
"CityName1": 
    { "OfficeName1": 
        [   
            {"name": RoomName1, "RoomProperty2": RoomValue1},
            {"name": RoomName2, "RoomProperty2": RoomValue2}
        ]
    }, 
    { "OfficeName2": [{...}]},
    { "OfficeNameX" : [{...}] },
"CityName2": {...},
"CityNameN": {...}}

Java类:

代码语言:javascript
复制
public class City {
  private Map<String, Object> additionalProperties = new HashMap<String, Object();

  private List<Office> _offices = new ArrayList<Office>();

  @JsonAnyGetter
  public Map<String, Object> getAdditionalProperties() {
    return this.additionalProperties;
  }

  @JsonAnySetter
  public void setAdditionalProperty(String name, Object value)
      throws IOException {
    _cityName = name;
    String officeJson = _mapper.writeValueAsString(value);
    StringBuilder sb = new StringBuilder(officeJson);
    _offices.add(_mapper.readValue(officeJson, Office.class));
    this.additionalProperties.put(name, value);
  }
}

public class Office {

  private String _officeName;

  private static final ObjectMapper _mapper = new ObjectMapper();

  private Map<String, Object> additionalProperties = new HashMap<String, Object>();

  private List<Room> _rooms = new ArrayList<Room>();

  @JsonAnyGetter
  public Map<String, Object> getAdditionalProperties() {
    return this.additionalProperties;
  }

  @JsonAnySetter
  public void setAdditionalProperty(String name, Object value)
      throws IOException {
    _officeName = name;
    String roomJson = _mapper.writeValueAsString(value);
    Room[] rooms  = _mapper.readValue(roomJson, Room[].class);
    _rooms.addAll(Arrays.asList(rooms));
    this.additionalProperties.put(name, value);
  }

  public List<Room> getRooms() {
    return _rooms;
  }

  public void setRooms(List<Room> rooms) {
    _rooms = rooms;
  }  
}

public class Room {

  private static final String NAME = "name";
  private static final String PROP_2 = "RoomProperty2";

  @JsonProperty(PROP_2)
  private String _propertyTwo;

  @JsonProperty(NAME)
  private String name;

  @JsonProperty(PROP_2)
  public String getPropertyTwo() {
    return _propertyTwo;
  }

  @JsonProperty(PROP_2)
  public void setPropertyTwo(String propTwo) {
    _propertyTwo = propTwo;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

那么,我该如何与杰克逊分析这个问题呢?目前,我正在使用@JsonAnySetter获取名称,并将其保存为城市或办公室名称,然后将发送给JsonAnySetter的值发送给适当的嵌套类。真正的问题是拿到一份伦敦金融城的办公室名单。当使用mapper.readvalues(String,Office.class)时,只返回每个城市的最后一个办公室的迭代器。伙计们有什么想法吗?

抱歉,如果这看起来很混乱的话!很乐意回答我提出的任何问题。

谢谢你的帮助!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-05-08 02:14:27

我认为最好的解决方案是在这里编写您自己的去列器,因为您的JSON文档并不能很好地映射到您想要的类结构。

下面的解决方案将每个城市读取为Map<String, List<Room>>,将城市集合读入Map<String, City>,然后在反序列化器中从这些城市中创建CityOffice对象。

Room.java和您的一样,下面是其他的:

Cities.java

代码语言:javascript
复制
@JsonDeserialize(using=CitiesDeserializer.class)
public class Cities implements Iterable<City> {

    private final List<City> cities;

    public Cities(final List<City> cities) {
        this.cities = cities;
    }

    public Cities() {
        this.cities = new ArrayList<>();
    }

    public List<City> getCities() {
        return cities;
    }

    @Override
    public Iterator<City> iterator() {
        return cities.iterator();
    }
}

CitiesDeserialiser.java

代码语言:javascript
复制
public class CitiesDeserializer extends JsonDeserializer<Cities> {
    private static final TypeReference<Map<String, City>> TYPE_REFERENCE = new TypeReference<Map<String, City>>() {};

    @Override
    public Cities deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException {
        final Map<String, City> map = jp.readValueAs(TYPE_REFERENCE);
        List<City> cities = new ArrayList<>();
        for(Map.Entry<String, City> entry : map.entrySet()) {
            City city = entry.getValue();
            city.setName(entry.getKey());
            cities.add(city);
        }
        return new Cities(cities);
    }
}

City.java

代码语言:javascript
复制
@JsonDeserialize(using=CityDeserialzer.class)
public class City {

    private String name;

    private List<Office> offices;

    // Setters and getters
}

CityDeserializer.java

代码语言:javascript
复制
public class CityDeserialzer extends JsonDeserializer<City> {
    private static final TypeReference<Map<String, List<Room>>> TYPE_REFERENCE = new TypeReference<Map<String, List<Room>>>() {};

    @Override
    public City deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException {
        final Map<String, List<Room>> map = jp.readValueAs(TYPE_REFERENCE);
        List<Office> offices = new ArrayList<>();
        for(Map.Entry<String, List<Room>> entry : map.entrySet()) {
            Office office = new Office();
            office.setName(entry.getKey());
            office.setRooms(entry.getValue());
            offices.add(office);
        }
        City city = new City();
        city.setOffices(offices);
        return city;
    }
}

Office.java

代码语言:javascript
复制
public class Office {

    private String name;

    private List<Room> rooms;

    // Setters and getters
}

这里有一个测试来证明它是有效的:

杰森:

代码语言:javascript
复制
{
    "CityName1": {
        "OfficeName1": [ {
                "name": "RoomName1",
                "RoomProperty2": "RoomValue1"
            }, {
                "name": "RoomName2",
                "RoomProperty2": "RoomValue2"
            } ],
        "OfficeName2": [ {
                "name": "RoomName3",
                "RoomProperty2": "RoomValue3"
            }, {
                "name": "RoomName4",
                "RoomProperty2": "RoomValue4"
            } ]
    },
    "CityName2": {
        "OfficeName3": [ {
                "name": "RoomName5",
                "RoomProperty2": "RoomValue5"
            }, {
                "name": "RoomName6",
                "RoomProperty2": "RoomValue6"
            } ],
        "OfficeName4": [ {
                "name": "RoomName7",
                "RoomProperty2": "RoomValue7"
            }, {
                "name": "RoomName8",
                "RoomProperty2": "RoomValue8"
            } ]
    }
}

Test.java

代码语言:javascript
复制
public class Test {

    public static void main(String[] args) {
        String json = ...
        ObjectMapper mapper = new ObjectMapper();
        Cities cities = mapper.readValue(json, Cities.class);
        for(City city : cities) {
            System.out.println(city.getName());
            for(Office office : city.getOffices()) {
                System.out.println("\t" + office.getName());
                for(Room room : office.getRooms()) {
                    System.out.println("\t\t" + room.getName());
                    System.out.println("\t\t\t" + room.getPropertyTwo());
                }
            }
        }
    }
}

输出:

代码语言:javascript
复制
CityName1
    OfficeName1
        RoomName1
            RoomValue1
        RoomName2
            RoomValue2
    OfficeName2
        RoomName3
            RoomValue3
        RoomName4
            RoomValue4
CityName2
    OfficeName3
        RoomName5
            RoomValue5
        RoomName6
            RoomValue6
    OfficeName4
        RoomName7
            RoomValue7
        RoomName8
            RoomValue8
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30113300

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档