Details
-
Bug
-
Status: Closed
-
Major
-
Resolution: Fixed
-
2.2
-
None
-
None
Description
Hello,
I have noticed that the array type is not properly handled by the JSONConfiguration (or AbstractYAMLBasedConfiguration)
If we take the example from json.org
{ "menu": { "id": "file", "value": "File", "popup": { "menuitem": [ { "value": "New", "onclick": "CreateNewDoc()" }, { "value": "Open", "onclick": "OpenDoc()" }, { "value": "Close", "onclick": "CloseDoc()" } ] } } }
I would have expect the following call to return "New"
configuration.getString("menu.popup.menuitem(0).value")
The issue, I guess, is that only the Map type is handled by AbstractYAMLBasedConfiguration in a recursive way and not the list type.
I had a custom JSONConfiguration implementation before supporting this use case, sorry for the code, it could be a bit messy and old, but it is maybe clearer to understand my issue
@Override @SuppressWarnings("unchecked") public void read(Reader in) throws ConfigurationException { try { Object jsonRoot = MAPPER.readValue(in, Object.class); List<ImmutableNode.Builder> roots = createHierarchy(jsonRoot); if (roots.size() != 1) { throw new ConfigurationException("The configuration only support a single root"); } getSubConfigurationParentModel().mergeRoot(roots.get(0).create(), null, null, null, null); } catch (IOException ex) { throw new ConfigurationException("Invalid JsonConfiguration", ex); } } @SuppressWarnings("unchecked") private static List<ImmutableNode.Builder> createHierarchy(Object value) { if (value instanceof Map) { ImmutableNode.Builder result = new ImmutableNode.Builder(); Map<String, ?> map = (Map<String, ?>) value; for (Map.Entry<String, ?> entry : map.entrySet()) { List<ImmutableNode.Builder> children = createHierarchy(entry.getValue()); for (ImmutableNode.Builder child : children) { child.name(entry.getKey()); result.addChild(child.create()); } } return Collections.singletonList(result); } else if (value instanceof List) { List list = (List) value; List<ImmutableNode.Builder> result = new ArrayList<>(list.size()); for (Object item : list) { List<ImmutableNode.Builder> children = createHierarchy(item); for (ImmutableNode.Builder child : children) { result.add(child); } } return result; } ImmutableNode.Builder result = new ImmutableNode.Builder(); result.value(value); return Collections.singletonList(result); }