使用 Jackson / Gson API 将 Map<String, Set> 转换为 POJO

时间:2021-01-12 13:41:34

标签: java json jackson gson jackson-databind

我使用第三方 API 以 Map> 形式返回数据,该数据采用 JSON 格式,其中键是字符串,与类变量和 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);

1 个答案:

答案 0 :(得分:0)

您的问题似乎很具体,我认为没有内置的方法可以做到这一点,您可以使用 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();
    }
});
相关问题