1

I am reading an REST API in JSON format. When reading the JSON i cannot extract the leaves with JSONPath. So what i would like to do is run thru the JSON string with Java and get the values i need, they are always in the same order. This is the JSON string i need to extract values from:

{
"10516": {
    "estimated": {
        "value": 10.0,
        "text": "10.0"
    },
    "completed": {
        "value": 7.5,
        "text": "7.5"
    }
},
"10244": {
    "estimated": {
        "value": 15.5,
        "text": "15.5"
    },
    "completed": {
        "value": 7.5,
        "text": "7.5"
    }
},
"10182": {
    "estimated": {
        "value": 12.0,
        "text": "12.0"
    },
    "completed": {
        "value": 10.0,
        "text": "10.0"
    }
},
"10391": {
    "estimated": {
        "value": 16.0,
        "text": "16.0"
    },
    "completed": {
        "value": 3.0,
        "text": "3.0"
    }
},
"10183": {
    "estimated": {
        "value": 12.0,
        "text": "12.0"
    },
    "completed": {
        "value": 7.0,
        "text": "7.0"
    }
},
"10123": {
    "estimated": {
        "value": 11.5,
        "text": "11.5"
    },
    "completed": {
        "value": 5.5,
        "text": "5.5"
    }
},
"10447": {
    "estimated": {
        "value": 7.0,
        "text": "7.0"
    },
    "completed": {
        "value": 3.0,
        "text": "3.0"
    }
}}

As you can see the ID 10516 has estimated and completed, i would like to extract those values for each ID. So the output should look like this:

ID    | ESTIMATED  |  COMPLETED
10516 | 10.0       |  7.5
10244 | 15.5       |  7.5
10182 | 12.0       |  10.0

and so on..

it is important that for every ID the values are in the same row because i need to upload them to my PostgreSQL db and join this data with other data on the ID.

My idea is to coun't the values surrounded by quotation marks and get the 1st, 5th, 9th, 10th, 14th and 18th value and so on. because the JSON string is always in the same order i guess it could be done like that..

please help out and keep in mind i don't have any experience in java at all and the implementation will be done in Talend Open Studio. also see my other question that raised this question because JSONPath cannot help me: Extract leaves from JSON file with JSONpath

Community
  • 1
  • 1
  • If you want to use Java, use a proper JSON parser. Trying to parse this as plaintext is going to give you more trouble than it's worth. – RealSkeptic Oct 13 '16 at 13:22
  • thanks for the response @RealSkeptic, but what JSON parser will help me extract the leaves (`10516`,`10244` etc.)? because with JSONPath it seems that you cannot extract values without labels... when extracting the values from `estimated` and `completed` i have no issues because they have a label i can address, – StackedOverflow Oct 13 '16 at 13:29
  • 1
    Any JSON parser will allow you to do that. Just don't insist on using XPath to do it. Just parse the object and iterate the keys. See [How to parse JSON in Java](http://stackoverflow.com/q/2591098/4125191) – RealSkeptic Oct 13 '16 at 13:37

2 Answers2

0

what JSON parser will help me extract the leaves (10516,10244 etc.)?

Examples with Jackson (com.fasterxml.jackson.core:jackson-databind:2.0.6):

The quick and dirty approach:

    String json = "{\n" +
            "\"10516\": {\"estimated\": {\"value\": 10.0,\"text\": \"10.0\"},\"completed\": {\"value\": 7.5,\"text\": \"7.5\"}},\n" +
            "\"10244\": {\"estimated\": {\"value\": 15.5,\"text\": \"15.5\"},\"completed\": {\"value\": 7.5,\"text\": \"7.5\"}},\n" +
            "\"10182\": {\"estimated\": {\"value\": 12.0,\"text\": \"12.0\"},\"completed\": {\"value\": 10.0,\"text\": \"10.0\"}}\n" +
            "}";

    ObjectMapper mapper = new ObjectMapper();
    TypeReference<Map> typeRef = new TypeReference<Map>(){};
    try {
        Map<String, Object> map = mapper.readValue(json, typeRef);
        System.out.println(map);
    } catch (IOException e) {
        // log error
    }

Output:

{10516={estimated={value=10.0, text=10.0}, completed={value=7.5, text=7.5}}, 10244={estimated={value=15.5, text=15.5}, completed={value=7.5, text=7.5}}, 10182={estimated={value=12.0, text=12.0}, completed={value=10.0, text=10.0}}}

This way you can parse any JSON string. You can of course access all JSON fields as long as you cast to the corresponding type:

        Map item = (Map) map.get("10182");
        System.out.println(item);

        Map estimated = (Map) item.get("estimated");
        Double value = (Double) estimated.get("value");
        System.out.println(value);

        String text = (String) estimated.get("text");
        double newValue = value + 10;
        System.out.println("old text: "+text+", new value: "+newValue);

Output:

{estimated={value=12.0, text=12.0}, completed={value=10.0, text=10.0}}
12.0
old text: 12.0, new value: 22.0

The cleaner, better approach

Of course, a better approach would be to define some model classes like the following:

class Model {
    ModelContent estimated;
        public ModelContent getEstimated() {return estimated;}
        public void setEstimated(ModelContent estimated) { this.estimated = estimated;}
    ModelContent completed;
        public ModelContent getCompleted() {return completed;}
        public void setCompleted(ModelContent completed) { this.completed = completed;}
    public Model() {}
}


class ModelContent {
    Double value;
        public Double getValue() {return value;}
        public void setValue(Double value) { this.value = value;}
    String text;
        public String getText() {return text;}
        public void setText(String text) {this.text = text;}
    public ModelContent() {}
}

And use them as the value type for the root map:

    ObjectMapper mapper = new ObjectMapper();
    TypeReference<Map<String,Model>> typeRef = new TypeReference<Map<String,Model>>(){};
    try {
        Map<String, Model> map = mapper.readValue(json, typeRef);
        Model item = map.get("10182");
        ModelContent completed = item.getCompleted();
        Double completedValue = completed.getValue();
        System.out.println("value: "+completedValue);
    } catch (IOException e) {
        // log error
    }

Output:

value: 10.0
walen
  • 7,103
  • 2
  • 37
  • 58
0
String jsonString="YOUR JSON STRING";
JSONObject mainObject=new JSONObject(jsonString);
Iterator<String> keys= mainObject.keys();
while (keys.hasNext()) 
    {
    String keyValue = (String)keys.next();
    JSONObject obj1 = mainObject.getJSONObject(keyValue);
    JSONObject estimatedObj = obj1.getJSONObject("estimated");
    JSONObject completedObj = obj1.getJSONObject("completed");
    System.out.print(keyvalue+"-"+estimatedObj.getString("text")+"-"+completedObj.getString("text"));
    System.out.println();
    }
Aakash
  • 5,181
  • 5
  • 20
  • 37