Yaron
Yaron

Reputation: 2709

Jackson - Get an entry inside array

I have the following JSON source:

{
    "my-systems": [{
            "SYSTEM_A": [{
                    "parameter-name": "a_param1",
                    "parameter-display-name": "parameter 1",
                    "optional": "true"
                },
                {
                    "parameter-name": "a_param2",
                    "parameter-display-name": "Parameter 2",
                    "optional": "false"
                }
            ]
        },
        {
            "SYSTEM_B": [{
                    "parameter-name": "b_param1",
                    "parameter-display-name": "Parameter 1",
                    "optional": "true"
                },
                {
                    "parameter-name": "b_param2",
                    "parameter-display-name": "Parameter 2",
                    "optional": "false"
                }
            ]
        }
    ]
}

I try to read it into a map of Map<String, SystemParameter[]>.
I have this code which I'm really not sure if it's the best approach for my goal.

ArrayNode systemsArr = (ArrayNode)jsonDoc.get("my-systems");
if(systemsArr!= null && !systemsArr.isEmpty()){
    for(JsonNode systemNode : systemsArr ){
        ObjectNode systemObj = (ObjectNode)systemNode;

        System.out.println(systemObj .textValue());
    }
}

Is it a valid approach? How do I get the name of the system (SYSTEM_A, SYSTEM_B) and convert the contained parameters into a parameters objects array?

Upvotes: 0

Views: 277

Answers (2)

QuickSilver
QuickSilver

Reputation: 4045

You just need to use jackson-databind and jackson-annotations jar in your dependency and you should be able to run below code

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class JsonParsing {

    public static void main(String[] args) throws IOException {
        String jsonFilePath = "src/main/resources/source.json"; // JSON File Path
        MySystems mySystems = new ObjectMapper().readValue(new File(jsonFilePath),MySystems.class);

        Map<String,SystemParameter[]> outputMap = new HashMap<>();
        for (Map<String,List<SystemParameter>> map :mySystems.mySystems) {
            for (String key :map.keySet()) {
                outputMap.put(key, map.get(key).toArray(new SystemParameter[0]));
            }
        }
        System.out.println(outputMap);

    }
}

class MySystems {
    @JsonProperty("my-systems")
    List<Map<String,List<SystemParameter>>> mySystems;
}

class SystemParameter {
    @JsonProperty("parameter-name")
    String paramName;

    @JsonProperty("parameter-display-name")
    String paramDispName;

    @JsonProperty("optional")
    String optional;
}

Upvotes: 1

sbsatter
sbsatter

Reputation: 581

Using an array 'my-systems' is of little use if all you're doing is keeping your keys unique. (I am assuming your SYSTEM_A may be different). Instead, I suggest you format the JSON data in the following way:

{
  "my-systems": [
    {
      "system-name" : {
        "name":"System_A",
        "parameters": [
          {
            "parameter-name": "a_param1",
            "parameter-display-name": "parameter 1",
            "optional": "true"
          },
          {
            "parameter-name": "a_param2",
            "parameter-display-name": "Parameter 2",
            "optional": "false"
          }
        ]
      }
   }
  ]
}

This method is clean, and allows you to catch the name of the system under the property 'system-name' and it's parameters are nested inside. You can simply declare a model and Jackson (or gson) will simply take care of everything.

If you'd rather parse the response separately or you have no control over the response, you can opt to go with your implementation but you do not need to convert to ObjectNode. You can use the samples below inside your for loop:

String f2Str = jsonNode.get("f2").asText();
double f2Dbl = jsonNode.get("f2").asDouble();
int    f2Int = jsonNode.get("f2").asInt();
long   f2Lng = jsonNode.get("f2").asLong();

where 'f2' is your key, and you can get the key using node.fieldNames().next() which is actually getting the property from an iterator.

You may also try the ones below, they seem better to handle.

JsonNode parent = ...;
for (Iterator<String> it = parent.fieldNames() ; it.hasNext() ; ) {
    String field = it.next();
    System.out.println(field + " => " + parent.get(field));
}
for (Iterator<Map.Entry<String,JsonNode>> it = parent.fields() ;
     it.hasNext() ; ) {
    Map.Entry<String,JsonNode> e = it.next();
    System.out.println(e.getKey() + " => " + e.getValue());
}

The latest examples are taken from here. Hope this helps.

Upvotes: 0

Related Questions