skip to Main Content

I’ve a Java object structure corresponding to following JSON:

{
  "parentClass": {
    "parentField1": "parentFieldValue1",
    "parentField2": "parentFieldValue2",
    "childClass": {
        "childField1": "childFieldValue1",
        "childField2": "childFieldValue2"
    },
    "childClassList": [
      {
        "stringField": "stringField1",
        "integerField": "integerField1"
      },
      {
        "stringField": "stringField2",
        "integerField": "integerField2"
      }
    ]
  }
}

I want to flatten it to following structure:

{
    "parentClass.parentField1": "parentFieldValue1",
    "parentClass.parentField2": "parentFieldValue2",
    "parentClass.childClass.childField1": "childFieldValue1",
    "parentClass.childClass.childField2": "childFieldValue2",
    "parentClass.childClassList[0].stringField": "stringField1",
    "parentClass.childClassList[0].integerField": "integerField1",
    "parentClass.childClassList[1].stringField": "stringField2",
    "parentClass.childClassList[1].integerField": "integerField2"
}

Is there a way to do it?

2

Answers


  1. Chosen as BEST ANSWER

    I've found a way using following code:

    convertToFlatMap("", obj, new HashMap<>())
    

    Implementation:

    private static Map<String, Object> convertToFlatMap(String prefix, Object obj, Map<String, Object> map) {
            if (obj == null) {
                return map;
            }
            if (obj instanceof Map) {
                Map<?, ?> objMap = (Map<?, ?>) obj;
                objMap.forEach((key, value) -> {
                    String fullKey = prefix.isEmpty() ? key.toString() : prefix + "." + key.toString();
                    convertToFlatMap(fullKey, value, map);
                });
            } else if (obj.getClass().isArray()) {
                Object[] array = (Object[]) obj;
                for (int i = 0; i < array.length; i++) {
                    String fullKey = prefix + "[" + i + "]";
                    convertToFlatMap(fullKey, array[i], map);
                }
            } else if (obj instanceof Iterable) {
                Iterable<?> iterable = (Iterable<?>) obj;
                int i = 0;
                for (Object item : iterable) {
                    String fullKey = prefix + "[" + i + "]";
                    convertToFlatMap(fullKey, item, map);
                    i++;
                }
            } else if (obj.getClass().isPrimitive() || obj instanceof String) {
                map.put(prefix, obj);
            } else {
                // recursively flatten nested object properties
                Map<String, Object> nestedMap = new HashMap<>();
                for (java.lang.reflect.Field field : obj.getClass().getDeclaredFields()) {
                    field.setAccessible(true);
                    String fullKey = prefix.isEmpty() ? field.getName() : prefix + "." + field.getName();
                    try {
                        Object fieldValue = field.get(obj);
                        convertToFlatMap(fullKey, fieldValue, nestedMap);
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException("Error accessing field " + field.getName() + " of object " + obj.getClass().getName());
                    }
                }
                map.putAll(nestedMap);
            }
            return map;
        }
    

  2. Library Josson has function flatten() to do the transformation.

    https://github.com/octomix/josson

    Josson josson = Josson.fromJsonString(
        "{" +
        "  "parentClass": {" +
        "    "parentField1": "parentFieldValue1"," +
        "    "parentField2": "parentFieldValue2"," +
        "    "childClass": {" +
        "        "childField1": "childFieldValue1"," +
        "        "childField2": "childFieldValue2"" +
        "    }," +
        "    "childClassList": [" +
        "      {" +
        "        "stringField": "stringField1"," +
        "        "integerField": "integerField1"" +
        "      }," +
        "      {" +
        "        "stringField": "stringField2"," +
        "        "integerField": "integerField2"" +
        "      }" +
        "    ]" +
        "  }" +
        "}");
    JsonNode node = josson.getNode("flatten('.', '[%d]')");
    System.out.println(node.toPrettyString());
    

    Output

    {
      "parentClass.parentField1" : "parentFieldValue1",
      "parentClass.parentField2" : "parentFieldValue2",
      "parentClass.childClass.childField1" : "childFieldValue1",
      "parentClass.childClass.childField2" : "childFieldValue2",
      "parentClass.childClassList[0].stringField" : "stringField1",
      "parentClass.childClassList[0].integerField" : "integerField1",
      "parentClass.childClassList[1].stringField" : "stringField2",
      "parentClass.childClassList[1].integerField" : "integerField2"
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search