当找到某个条目名称时,如何转换/修改地图列表中的嵌套地图?



示例: 这是它在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));
}
}
}

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

下面是如何使用杰克逊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.nonen" +
"      readonly: truen" +
"    MINOR:n" +
"      value: core.lookups.states.minorn" +
"      readonly: truen" +
"    MAJOR:n" +
"      value: core.lookups.states.majorn" +
"      readonly: truen" +
"  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>

这是一个可能的解决方案:

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;
}