有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在找到某个条目名称时转换/修改映射列表中的嵌套映射?

例如: 这是它在yaml结构中的外观:

    states:
      entries:
        NONE: 
          value: core.lookups.states.none
          readonly: true
        MINOR:
          value: core.lookups.states.minor
          readonly: true
        MAJOR: 
          value: core.lookups.states.major
          readonly: true
      readonly: true

这是转换后的外观:

    states:
      entries:
        - key: "NONE"
          value: core.lookups.states.none
          readonly: true
        - key:  "MINOR"
          value: core.lookups.states.minor
          readonly: true
        - key: "MAJOR"
          value: core.lookups.states.major
          readonly: true
      readonly: true

注意:可能有更多条目,但每个条目中的键“条目”都是相同的,如:

        states:
          entries:
            - key: "NONE"
              value: core.lookups.states.none
              readonly: true
            - key:  "MINOR"
              value: core.lookups.states.minor
              readonly: true
            - key: "MAJOR"
              value: core.lookups.states.major
              readonly: true
          readonly: true
        states2:
          entries:
            - key: "NONE"
              value: core.lookups.states2.none
              readonly: true
            - key:  "MINOR"
              value: core.lookups.states2.minor
              readonly: true
            - key: "MAJOR"
              value: core.lookups.states2.major
              readonly: true
          readonly: true

注意:可能有更多条目,但每个条目中的键“条目”都是相同的,如:

public static void hashMapper(Map<String, Object> lookups) throws ParseException
    {
        for (Map.Entry<String, Object> entry : lookups.entrySet())
        {
            String key = entry.getKey();
            Object value = entry.getValue();
            if (key.equals("entries"))
            {
                //modify the entry into list
            }
            else if (value instanceof Map)
            {
                Map<String, Object> subMap = (Map<String, Object>) value;
                hashMapper(subMap);
            }
            else
            {
                throw new IllegalArgumentException(String.valueOf(value));
            }

        }
    }

这就是我到目前为止所做的。每次当我找到带有条目值的键时,我都应该转换里面的条目。各州也可以有另一个父密钥


共 (2) 个答案

  1. # 1 楼答案

    下面是如何使用Jackson提供的YAMLFactory的快速演示:

    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
    
    import java.util.ArrayList;
    import java.util.LinkedHashMap;
    import java.util.List;
    import java.util.Map;
    
    public class YamlTest {
    
        private static final ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
    
        public static Map<String, State> convert(String yaml) throws Exception {
    
            Map<String, State> states = new LinkedHashMap<>();
            Map<String, Object> map = mapper.readValue(yaml, Map.class);
    
            for (String state : map.keySet()) {
                List<Entry> entryList = new ArrayList<>();
                Map<String, Object> statesMap = (Map<String, Object>) map.get(state);
                Map<String, Object> entriesMap = (Map<String, Object>) statesMap.get("entries");
    
                for (String entryKey : entriesMap.keySet()) {
                    Map<String, Object> entryValueMap = (Map<String, Object>) entriesMap.get(entryKey);
    
                    String value = (String) entryValueMap.get("value");
                    Boolean readonly = (Boolean) entryValueMap.get("readonly");
    
                    entryList.add(new Entry(entryKey, value, readonly));
                }
    
                Boolean readonlyState = (Boolean) statesMap.get("readonly");
    
                states.put(state, new State(entryList, readonlyState));
            }
    
            return states;
        }
    
        public static void main(String[] args) throws Exception {
    
            String input = "states:\n" +
                    "  entries:\n" +
                    "    NONE:\n" +
                    "      value: core.lookups.states.none\n" +
                    "      readonly: true\n" +
                    "    MINOR:\n" +
                    "      value: core.lookups.states.minor\n" +
                    "      readonly: true\n" +
                    "    MAJOR:\n" +
                    "      value: core.lookups.states.major\n" +
                    "      readonly: true\n" +
                    "  readonly: true";
    
            Map<String, State> states = convert(input);
            String yamlOut = mapper.writeValueAsString(states);
    
            System.out.println(yamlOut);
        }
    }
    
    class State {
    
        public List<Entry> entries;
        public boolean readonly;
    
        public State(List<Entry> entries, boolean readonly) {
            this.entries = entries;
            this.readonly = readonly;
        }
    }
    
    class Entry {
    
        public String key;
        public String value;
        public boolean readonly;
    
        public Entry(String key, String value, boolean readonly) {
            this.key = key;
            this.value = value;
            this.readonly = readonly;
        }
    }
    

    将打印:

     -
    states:
      entries:
      - key: "NONE"
        value: "core.lookups.states.none"
        readonly: true
      - key: "MINOR"
        value: "core.lookups.states.minor"
        readonly: true
      - key: "MAJOR"
        value: "core.lookups.states.major"
        readonly: true
      readonly: true
    

    我使用了这些依赖项:

    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-yaml</artifactId>
        <version>2.9.8</version>
    </dependency>
    
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
        <version>2.9.8</version>
    </dependency>
    
  2. # 2 楼答案

    以下是一个可能的解决方案:

    public static void main(String[] args) {
        Map<String,Object> root = new HashMap<>();
        Map<String,Object> states = new HashMap<>();
        root.put("states", states);
        Map<String,Object> entries = new HashMap<>();
        states.put("entries", entries);
        Map<String,Object> none = new HashMap<>();
        entries.put("NONE", none);
        none.put("value", "core.lookups.states.none");
        none.put("readonly", true);
        Map<String,Object> minor = new HashMap<>();
        entries.put("MINOR", minor);
        minor.put("value", "core.lookups.states.minor");
        minor.put("readonly", true);
        Map<String,Object> major = new HashMap<>();
        entries.put("MAJOR", major);
        major.put("value", "core.lookups.states.minor");
        major.put("readonly", true);
        states.put("readonly", true);
        System.out.println(root);
        System.out.println(convertRoot(root));
    }
    
    private static Map<String,Object> convertRoot(Map<String,Object> root) {
        Map<String,Object> result = new LinkedHashMap<>();
        for (Map.Entry<String,Object> e: root.entrySet()) {
            String key = e.getKey();
            Object value = e.getValue();
            if (key.startsWith("states") && value instanceof Map) {
                value = convertStates((Map<String,Object>)value);
            }
            result.put(key, value);
        }
        return result;
    }
    
    private static Map<String,Object> convertStates(Map<String,Object> states) {
        Map<String,Object> result = new LinkedHashMap<>();
        for (Map.Entry<String,Object> e: states.entrySet()) {
            String key = e.getKey();
            Object value = e.getValue();
            if (key.equals("entries") && value instanceof Map) {
                value = toList((Map<String,Object>)value);
            }
            result.put(key, value);
        }
        return result;
    }
    
    private static List<Object> toList(Map<String,Object> map) {
        List<Object> result = new ArrayList<>();
        for (Map.Entry<String,Object> e: map.entrySet()) {
            String key = e.getKey();
            Object value = e.getValue();
            if (value instanceof Map) {
                Map<String,Object> elm
                        = new HashMap<>((Map<String,Object>)value);
                elm.put("key", key);
                value = elm;
            }
            result.add(value);
        }
        return result;
    }
    

    更新:就地转换

    public static void main(String[] args) {
        Map<String,Object> root = new HashMap<>();
        Map<String,Object> states = new HashMap<>();
        root.put("states", states);
        Map<String,Object> entries = new HashMap<>();
        states.put("entries", entries);
        Map<String,Object> none = new HashMap<>();
        entries.put("NONE", none);
        none.put("value", "core.lookups.states.none");
        none.put("readonly", true);
        Map<String,Object> minor = new HashMap<>();
        entries.put("MINOR", minor);
        minor.put("value", "core.lookups.states.minor");
        minor.put("readonly", true);
        Map<String,Object> major = new HashMap<>();
        entries.put("MAJOR", major);
        major.put("value", "core.lookups.states.minor");
        major.put("readonly", true);
        states.put("readonly", true);
        System.out.println(root);
        convertRoot(root);
        System.out.println(root);
    }
    
    private static void convertRoot(Map<String,Object> root) {
        Map<String,Object> result = new LinkedHashMap<>();
        for (String key: root.keySet().toArray(new String[root.size()])) {
            Object value = root.get(key);
            if (key.startsWith("states") && value instanceof Map) {
                convertStates((Map<String,Object>)value);
            }
        }
    }
    
    private static void convertStates(Map<String,Object> states) {
        Map<String,Object> result = new LinkedHashMap<>();
        for (String key: states.keySet().toArray(new String[states.size()])) {
            Object value = states.get(key);
            if (key.startsWith("entries") && value instanceof Map) {
                states.put(key, toList((Map<String,Object>)value));
            }
        }
    }
    
    private static List<Object> toList(Map<String,Object> map) {
        List<Object> result = new ArrayList<>();
        for (Map.Entry<String,Object> e: map.entrySet()) {
            String key = e.getKey();
            Object value = e.getValue();
            if (value instanceof Map) {
                Map<String,Object> elm
                        = new HashMap<>((Map<String,Object>)value);
                elm.put("key", key);
                value = elm;
            }
            result.add(value);
        }
        return result;
    }