【问题标题】:Convert Map<String, Set> to POJO using Jackson / Gson API使用 Jackson / Gson API 将 Map<String, Set> 转换为 POJO
【发布时间】:2021-01-12 13:41:34
【问题描述】:

我正在使用第三方 API 以 JSON 格式的 Map> 形式返回数据,其中 key 是字符串,与类变量和 Set 相同包含相关值,它将是 String,即使它是 Set,也只需要一个值。

现在一种方法是遍历 Map 并使用反射来填充 POJO。

我想知道 Jackson / Gson API 是否可用于填充 POJO。我都试过了,但是 POJO 中没有填充值。

JSON:
{
    "Id": [
        "345"
    ],
    "Name": [
        "John"
    ]
}

POJO:
public class Employee implements Serializable {
  private String id;
  private String name;

  // getter / setter
}

My Code:

Map<String, Set<?>> data = someObject.getDataSet();

ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Employee employee = mapper.convertValue(data, Employee.class);
System.out.println(employee);

更新: 我试过了,但 POJO 仍然是空的

Map<String, Set<?>> data = someObject.getDataSet();

Map<String, String> map = data.entrySet().stream()
        .filter(entry -> entry.getValue() != null)
        .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().iterator().next().toString()));

Employee employee = null;

ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Employee = mapper.convertValue(map, Employee.class);
System.out.println(employee);

Gson gson = new Gson();
JsonElement jsonElement = gson.toJsonTree(map);
Employee = gson.fromJson(jsonElement, Employee.class);
System.out.println(employee);

【问题讨论】:

  • [ "345" ] 表示它是一个数组,所以你可以改变String id;列出 id
  • @NehaK 这个问题表明他想单独保存它,而不是在一个列表中
  • @PiotrŻmudzin 你是对的。即使值是数组,我也想填充 POJO。

标签: java json jackson gson jackson-databind


【解决方案1】:

您的问题似乎很具体,我认为没有内置的方法可以做到这一点,您可以使用 Jackson 加载整个树并将节点映射到 POJO

示例:

ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(json);
Iterator<JsonNode> ids = root.get("Id").iterator();
Iterator<JsonNode> names = root.get("Names").iterator();

while (ids.hasNext()) {
    String id = ids.next().asText();
    String name = null;
    if (names.hasNext()) {
        name = names.next().asText();
    }
    employees.add(new Employee(id, name));
}

另一种方式:

JsonNode root = objectMapper.readTree(json);
        
Map<String, Iterator<JsonNode>> iterators = new HashMap<>();
root.fieldNames().forEachRemaining(name -> iterators.put(name, root.get(name).iterator()));

List<Map<String, String>> allAttributes = new ArrayList<>();
while (true) {
    Map<String, String> attributes = new HashMap<>();
    for (Map.Entry<String, Iterator<JsonNode>> e : iterators.entrySet()) {
        if (e.getValue().hasNext()) {
            attributes.put(e.getKey(), e.getValue().next().asText());
        }
    }
    if (attributes.size() != 0) {
        allAttributes.add(attributes);
    } else {
        break;
    }
}

List<Employee> employees = allAttributes.stream()
    .map(this::mapToEmployee)
    .collect(Collectors.toList());

然后添加将属性值映射到 POJO 的方法

你也可以不使用映射方法:

JsonNode root = mapper.readTree(json);

Map<String, Iterator<JsonNode>> iterators = new HashMap<>();
root.fieldNames().forEachRemaining(name -> iterators.put(name, 
root.get(name).iterator()));

List<JsonNode> nodes = new ArrayList<>();
while (true) {
    boolean hasNext = false;
    ObjectNode node = mapper.createObjectNode();
    for (Map.Entry<String, Iterator<JsonNode>> e : iterators.entrySet()) {
        if (e.getValue().hasNext()) {
            hasNext = true;
            node.put(e.getKey(), e.getValue().next().asText());
        }
    }
    if (hasNext) {
        nodes.add(node);
    } else {
        break;
    }
}

List<Employee> employees = new ArrayList<>();
nodes.forEach(node -> {
    try {
        employees.add(mapper.treeToValue(node, Employee.class));
    } catch (JsonProcessingException e) {
        e.printStackTrace();
    }
});

【讨论】:

  • 会有30-35个属性,你的例子不行。
猜你喜欢
  • 2013-05-01
  • 1970-01-01
  • 2021-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-05
相关资源
最近更新 更多