获取带有未展开的 json 列表的嵌套 json?

问题描述 投票:0回答:1

测试案例1:

输入

[{"key1": {"valueA": "", "valueB": ""}},
{"key2": {"valueC": "key3"}},
{"key3": {"valueD": "", "valueE": ""}}]

输出

[{"key1": {"valueA": "", "valueB": ""}},
{"key2": {"valueC": {"valueD": "", "valueE": ""}}]

测试案例2:

输入

[{"key1": {"valueA": "key2"}},
{"key2": {"valueB": "key3"}},
{"key3": {"valueC": "", "valueD": ""}}]

输出

[{"key1": {"valueA": {"valueB": {"valueC": "", "valueD": ""}}}}]

约束

  • 所有值都应该是空字符串或对象。

  • 深度 1 json 对象(

    {"key1": ...}
    ,
    {"key2": ...}
    , ...) 应该只有一个键值元素。

  • 任务可以递归执行,这意味着遍历不应该限制在某个级别。

我在这个问题上纠结了一个星期...请帮我解决或命名java库,以便我看一下源代码。

java json deserialization nested-loops
1个回答
0
投票

这里有一个算法和一个实现。

算法

  1. 获取对应于 Map 值(而不是 String)的所有键,将它们放入
    objectMap
    .
  2. rootKeys
    中的键填充
    objectMap
    。这些将是生成的地图中的顶级键。
  3. 递归遍历
    objectMap
    映射,替换非空字符串值(例如,在
    "valueC": key3"
    中,
    "key3"
    被替换)。如果更换了钥匙,请将其从
    rootKeys
    .
  4. 中删除
  5. 序列化
    rootKeys
    (具有相应的值)。

实施

import com.google.gson.Gson;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

class RecursiveJsonFlattener {
    private final Map<String, Map<String, Object>> objectMap = new HashMap<>();
    private final Set<String> rootKeys = new HashSet<>();
    private final Object[] jsonData;
    private final Gson serializer = new Gson();

    public RecursiveJsonFlattener(String jsonData) {
        this.jsonData = serializer.fromJson(jsonData, Object[].class);
    }

    public String getFlattened() {
        for (var obj : jsonData) {
            if (obj instanceof Map) {
                addToKeys((Map<String, Object>) obj);
            }
        }
        rootKeys.addAll(objectMap.keySet());

        for (var map : objectMap.values()) {
            substituteStringValues(map);
        }

        var resultingMap = rootKeys.stream().collect(Collectors.toMap(key -> key, objectMap::get));
        return serializer.toJson(resultingMap);
    }

    private void addToKeys(Map<String, Object> map) {
        for (var entry : map.entrySet()) {
            if (!(entry.getValue() instanceof String)) {
                objectMap.put(entry.getKey(), (Map<String, Object>) entry.getValue());
                addToKeys((Map<String, Object>) entry.getValue());
            }
        }
    }

    private void substituteStringValues(Map<String, Object> map) {
        for (var entry : map.entrySet()) {
            var value = entry.getValue();
            if (value instanceof String && !value.equals("")) {
                map.put(entry.getKey(), objectMap.get(value));
                rootKeys.remove(value);
            } else if (entry.getValue() instanceof Map) {
                substituteStringValues((Map<String, Object>) value);
            }
        }
    }
}

用法:

public class Main {
    public static void main(String[] args) {
        String jsonString = "[{\"key1\": {\"valueA\": \"\", \"valueB\": \"\"}},\n" +
                "{\"key2\": {\"valueC\": \"key3\"}},\n" +
                "{\"key3\": {\"valueD\": \"\", \"valueE\": \"\"}}]";
        System.out.println(new RecursiveJsonFlattener(jsonString).getFlattened());
        // prints {"key1":{"valueA":"","valueB":""},"key2":{"valueC":{"valueD":"","valueE":""}}}
    }
}

© www.soinside.com 2019 - 2024. All rights reserved.