Home > database >  Json manipulation and conversion in Java
Json manipulation and conversion in Java

Time:02-01

I have an input json like:

{
    "Employee": [
      {
        "employee1.id": 1
      },
      {
        "employee1.name": "John"
      },
      {
        "employee1.address.street": "main street"
      },
      {
        "employee1.address.pin": "123456"
      },
      {
        "employee2.id": 2
      },
      {
        "employee2.name": "Mike"
      },
      {
        "employee2.address.street": "51 street"
      },
      {
        "employee2.address.pin": "234543"
      }
    ]
}

And I am trying to convert it into:

{
    "employee1":{
        "id": 1,
        "name": "John",
        "address": {
            "street": "main street",
            "pin": "123456"
        }
    },
        "employee2":{
        "id": 2,
        "name": "Mike",
        "address": {
            "street": "51 street",
            "pin": "234543"
        }
    }
}

I tried to split the key from input json with dot i.e. '.' and tried to iterate over to construct a map: Map<String, Object> But the problem is the input json key depth can go beyond 2 i.e. in future the input key can be like:

{
    "employee1.address.tempAddress.street": "main street"
},
{
    "employee1.address.permanentAddress.street": "main street"
}

So, is there any library available to achieve this, or anything closely related to this using which I can achieve this?

CodePudding user response:

The comments about the input format being "weird" (to put it politely) are spot-on: This is a convoluted way to represent simple hierarchical data.

But sometimes we have to deal with sub-optimal input formats, that's why we can fix them like this:

  private static JSONObject arrayToStructure(JSONArray inputArray) {
    JSONObject output = new JSONObject();
    for (Object o : inputArray) {
      assert o instanceof JSONObject;
      JSONObject jso = (JSONObject) o;
      assert jso.length() == 1;
      String key = jso.keys().next();
      Object value = jso.get(key);
      setJsonPath(output, key, value);
    }
    return output;
  }

  private static void setJsonPath(JSONObject target, String key, Object value) {
    String[] keyParts = key.split("\\.");
    JSONObject parent = target;
    for (int i = 0; i < keyParts.length - 1; i  ) {
      String keyPart = keyParts[i];
      if (parent.has(keyPart)) {
        parent = parent.getJSONObject(keyPart);
      } else {
        JSONObject child = new JSONObject();
        parent.put(keyPart, child);
        parent = child;
      }
    }
    assert !parent.has(keyParts[keyParts.length - 1]);
    parent.put(keyParts[keyParts.length - 1], value);
  }

This code uses JSON-Java, probably better known as org.json:json.

And it can be used like this:

  public static void main(String[] args) {
    String input = """
        [
          {
            "employee1.id": 1
          },
          {
            "employee1.name": "John"
          },
          {
            "employee1.address.street": "main street"
          },
          {
            "employee1.address.pin": "123456"
          },
          {
            "employee2.id": 2
          },
          {
            "employee2.name": "Mike"
          },
          {
            "employee2.address.street": "51 street"
          },
          {
            "employee2.address.pin": "234543"
          }
        ]""";
    JSONArray inputArray = new JSONArray(input);
    JSONObject structure = arrayToStructure(inputArray);
    System.out.println(structure.toString(2));
  }

Note that this code is lacking proper sanity checks (some of which I've hinted at using assert) and the nature of this "protocol" means that you can get misleading, ambiguous or straight up malicious inputs. For example nothing stops the input from having both "employee1.id": 1 and "employee1.id": 2 in there. How that is to be interpreted is up to the parser and such ambiguity is a great source of bugs and potential security issues.

CodePudding user response:

Library Josson can do the transformation by one expression.

https://github.com/octomix/josson

Josson josson = Josson.fromJsonString(
    "{"  
    "  \"Employee\": ["  
    "    {"  
    "      \"employee1.id\": 1"  
    "    },"  
    "    {"  
    "      \"employee1.name\": \"John\""  
    "    },"  
    "    {"  
    "      \"employee1.address.street\": \"main street\""  
    "    },"  
    "    {"  
    "      \"employee1.address.pin\": \"123456\""  
    "    },"  
    "    {"  
    "      \"employee2.id\": 2"  
    "    },"  
    "    {"  
    "      \"employee2.name\": \"Mike\""  
    "    },"  
    "    {"  
    "      \"employee2.address.street\": \"51 street\""  
    "    },"  
    "    {"  
    "      \"employee2.address.pin\": \"234543\""  
    "    }"  
    "  ]"  
    "}");
JsonNode node = josson.getNode("Employee.mergeObjects().unflatten('.')");
System.out.println(node.toPrettyString());

Output

{
  "employee1" : {
    "id" : 1,
    "name" : "John",
    "address" : {
      "street" : "main street",
      "pin" : "123456"
    }
  },
  "employee2" : {
    "id" : 2,
    "name" : "Mike",
    "address" : {
      "street" : "51 street",
      "pin" : "234543"
    }
  }
}
  • Related