1

I am trying to parse the content of JSON file text.json by using Jackson library.

What I want is to make a java method to get all keys and values of it, but so far in my code I get only the first key and the first value of the JSON file.

The code snippet I used as guidance to make my own Java class is the following:

public void parse(String json)  {
    JsonFactory factory = new JsonFactory();

    ObjectMapper mapper = new ObjectMapper(factory);
    JsonNode rootNode = mapper.readTree(json);  

    Iterator<Map.Entry<String,JsonNode>> fieldsIterator = rootNode.fields();
    while (fieldsIterator.hasNext()) {

        Map.Entry<String,JsonNode> field = fieldsIterator.next();
        System.out.println("Key: " + field.getKey() + "\tValue:" + field.getValue());
    }
}

And my Java class that I created is shown below:

import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;

import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

public class JacksonStreamExample {
    public static void main(String[] args) {
        try {
            //Create a JsonFactory instance
            JsonFactory factory = new JsonFactory();

            //Create a JsonParser instance to read from file c:\\text.json
            JsonParser jParser = factory.createJsonParser(new File("c:\\text.json"));

            /*Create an ObjectMapper instance to provide a pointer
             * to root node of the tree after reading the JSON
             */
            ObjectMapper mapper = new ObjectMapper(factory);

            //Create tree from JSON
            JsonNode rootNode = mapper.readTree(jParser);  

            Iterator<Map.Entry<String,JsonNode>> fieldsIterator = rootNode.getFields();
            while (fieldsIterator.hasNext()) {
                Map.Entry<String,JsonNode> field = fieldsIterator.next();
                System.out.println("Key: " + field.getKey() + "\tValue:" + field.getValue());
            }

            jParser.close();

        } catch (JsonGenerationException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

My Eclipse output is the following which creates only 1 pair(key-value):

Key: cells  Value:[{"type":"basic.Circle","size":{"width":90,"height":54},"position":{"x":-80,"y":200},"angle":0,"id":"cae4c219-c2cd-4a4b-b50c-0f269963ca24","embeds":"","z":1,"wi_name":"START","wi_displayName":"START","wi_description":"","wi_join":"<None>","wi_split":"<None>","wi_performingRole":"<None>","wi_expected_activity_time":null,"wi_expected_user_time":null,"wi_maximum_activity_time":null,"wi_initial_delay":null,"wi_time_unit":"Seconds","wi_required_transitions_for_AND_JOIN":null,"wi_custom_page":"","attrs":{"circle":{"fill":"#000000","width":50,"height":30,"stroke-width":1,"stroke-dasharray":"0"},"text":{"font-size":10,"text":"START","fill":"#ffffff","font-family":"Arial","stroke":"#000000","stroke-width":0,"font-weight":400}}},{"type":"basic.Circle","size":{"width":90,"height":54},"position":{"x":210,"y":200},"angle":0,"id":"d23133e0-e516-4f72-8127-292545d3d479","embeds":"","z":2,"wi_name":"END","wi_displayName":"END","wi_description":"","wi_join":"<None>","wi_split":"<None>","wi_performingRole":"<None>","wi_expected_activity_time":null,"wi_expected_user_time":null,"wi_maximum_activity_time":null,"wi_initial_delay":null,"wi_time_unit":"Seconds","wi_required_transitions_for_AND_JOIN":null,"wi_custom_page":"","attrs":{"circle":{"fill":"#000000","width":50,"height":30,"stroke-width":1,"stroke-dasharray":"0"},"text":{"font-size":10,"text":"END","fill":"#ffffff","font-family":"Arial","stroke":"#000000","stroke-width":0,"font-weight":400}}},{"type":"basic.Rect","position":{"x":-80,"y":370},"size":{"width":90,"height":54},"angle":0,"id":"a53898a5-c018-45c4-bd3f-4ea4d69f58ed","embeds":"","z":3,"wi_name":"ACTIVITY_1","wi_displayName":"ACTIVITY 1","wi_description":"","wi_join":"<None>","wi_split":"<None>","wi_performingRole":"<None>","wi_expected_activity_time":null,"wi_expected_user_time":null,"wi_maximum_activity_time":null,"wi_initial_delay":null,"wi_time_unit":"Seconds","wi_required_transitions_for_AND_JOIN":null,"wi_custom_page":"","attrs":{"rect":{"width":50,"height":30,"rx":2,"ry":2,"stroke-width":1,"stroke-dasharray":"0"},"text":{"text":"Activity","font-size":10,"font-family":"Arial","stroke":"#000000","stroke-width":0,"font-weight":400}}},{"type":"basic.Rect","position":{"x":220,"y":370},"size":{"width":90,"height":54},"angle":0,"id":"e2bd21f2-508d-44b9-9f68-e374d4fa87ea","embeds":"","z":4,"wi_name":"ACTIVITY_2","wi_displayName":"ACTIVITY 2","wi_description":"","wi_join":"<None>","wi_split":"<None>","wi_performingRole":"<None>","wi_expected_activity_time":null,"wi_expected_user_time":null,"wi_maximum_activity_time":null,"wi_initial_delay":null,"wi_time_unit":"Seconds","wi_required_transitions_for_AND_JOIN":null,"wi_custom_page":"","attrs":{"rect":{"width":50,"height":30,"rx":2,"ry":2,"stroke-width":1,"stroke-dasharray":"0"},"text":{"text":"Workitem","font-size":10,"font-family":"Arial","stroke":"#000000","stroke-width":0,"font-weight":400}}},{"type":"link","source":{"id":"cae4c219-c2cd-4a4b-b50c-0f269963ca24"},"target":{"id":"d23133e0-e516-4f72-8127-292545d3d479"},"router":{"name":"manhattan"},"labels":[{"position":0.5,"attrs":{"text":{"text":"Name"}}}],"id":"60ee7ff7-3a3b-487d-b581-49027e7bebe4","embeds":"","z":5,"attrs":{".marker-source":{"d":"M 10 0 L 0 5 L 10 10 z","transform":"scale(0.001)"},".marker-target":{"d":"M 10 0 L 0 5 L 10 10 z"},".connection":{"stroke":"black"}}},{"type":"link","source":{"id":"a53898a5-c018-45c4-bd3f-4ea4d69f58ed"},"target":{"id":"e2bd21f2-508d-44b9-9f68-e374d4fa87ea"},"router":{"name":"manhattan"},"labels":[{"position":0.5,"attrs":{"text":{"text":"Name"}}}],"id":"cea0d1c2-2c18-4bd7-ba35-d94918c6fc9b","embeds":"","z":6,"attrs":{".marker-source":{"d":"M 10 0 L 0 5 L 10 10 z","transform":"scale(0.001)"},".marker-target":{"d":"M 10 0 L 0 5 L 10 10 z"},".connection":{"stroke":"black"}}}]

I just need to make a method to put this code inside to get all key-value pairs:

//Create a JsonFactory instance
JsonFactory factory = new JsonFactory();

//Create a JsonParser instance to read from file c:\\text.json
JsonParser jParser = factory.createJsonParser(new File("c:\\text.json"));

/*Create an ObjectMapper instance to provide a pointer
 *to root node of the tree after reading the JSON
 */
ObjectMapper mapper = new ObjectMapper(factory);

//Create tree from JSON
JsonNode rootNode = mapper.readTree(jParser);  


Iterator<Map.Entry<String,JsonNode>> fieldsIterator = rootNode.getFields();
while (fieldsIterator.hasNext()) {

    Map.Entry<String,JsonNode> field = fieldsIterator.next();
    System.out.println("Key: " + field.getKey() + "\tValue:" + field.getValue());
}

How will I do it please?

Tom
  • 16,842
  • 17
  • 45
  • 54
  • 1
    can you share the json? if not here, may be on pastebin or gist? – Pavan Kumar Jan 04 '17 at 10:44
  • 1
    i meant the content of c:\\text.json – Pavan Kumar Jan 04 '17 at 10:46
  • 1
    Possible duplicate of [JAVA - Best approach to parse huge (extra large) JSON file](http://stackoverflow.com/questions/9390368/java-best-approach-to-parse-huge-extra-large-json-file) – DimaSan Jan 04 '17 at 10:48
  • I don't want a Java code in which I have to write on my own all JSON keys and values. I want it to happen automatically. That's the main difference comparing my problem to many other solutions for example JAVA - Best approach to parse huge (extra large) JSON file – Reputated_Enginius Jan 04 '17 at 11:22
  • @PavanKumar here is my JSON file http://pastebin.com/yvu0mHCR – Reputated_Enginius Jan 04 '17 at 11:41
  • @PavanKumar now I have a progress on the issue. Thanks to RobbyCornelissen who pointed out that I don't have a JSON object but a JSON array instead I have to change my code properly since so far I was parsing an array and treating it like an object . I will let you know. Thank you all. – Reputated_Enginius Jan 05 '17 at 08:52
  • I changed my code, my text.json and I improved my new question. Thank you all for your so far support. I am really close. – Reputated_Enginius Jan 05 '17 at 10:58
  • SO is no ordinary forum where one adds stuff like "[edited]" or "[solved]" into the title, so please stop doing that. – Tom Jan 09 '17 at 10:56
  • Thank you @Tom very much. I'll keep it in mind to be a better community contributor. – Reputated_Enginius Jan 09 '17 at 10:58
  • Thank you, that's nice to hear. – Tom Jan 09 '17 at 11:00

3 Answers3

2

You should use Jackson2 instead of Jackson1. As the error message specifies, Jackson1's JsonNode indeed does not have this fields() method, while Jackson2's version does.

In Jackson1, you would have to do something like this:

Iterator<String> fieldNameIterator = rootNode.getFieldNames();

while (fieldNameIterator.hasNext()) {
    String fieldName = fieldNameIterator.next();
    JsonNode fieldValue = rootNode.getFieldValue(fieldName);

    System.out.println("Key: " + fieldName + "\tValue:" + fieldValue);
}
Robby Cornelissen
  • 91,784
  • 22
  • 134
  • 156
  • I changed my code and I incorporated yours. The error is removed but in console I see nothing. Please take a look in my edited code. Thank you very much. Keep in mind that I have the following warning: Description Resource Path Location Type The method getFieldValue(String) from the type JsonNode is deprecated JacksonStreamExample.java /JsonToXML/src line 29 Java Problem – Reputated_Enginius Jan 04 '17 at 11:36
  • 1
    @user6681439: So the problem in your question was solved? If yes, you ought to accept the answer given. If fixing the problem meant you encountered a new one, you could ask a new question. – Henrik Aasted Sørensen Jan 04 '17 at 20:25
  • 1
    *The error is removed but in console I see nothing.* Makes sense. You're parsing an array and treating it like an object. – Robby Cornelissen Jan 05 '17 at 01:00
  • @RobbyCornelissen you are perfectly right. That is why I was seeing nothing in console. I will fix it and I will let you know. Thank you so much. – Reputated_Enginius Jan 05 '17 at 08:13
  • @Henrik I changed my code, my text.json and I improved my new question. Thank you all for your so far support. I am really close. – Reputated_Enginius Jan 05 '17 at 10:59
2

I solved my problem by changing JSON library.

I used json-simple-1.1.1

My final code that worked is the following:

package jsontoxml;

import java.io.*;

import org.json.simple.parser.JSONParser;
import org.json.simple.*;
import java.util.*;


public class JacksonStreamExample {

   public static void main(String[] args) {
       JSONParser parser = new JSONParser();
     try {
        Object obj = parser.parse(new FileReader("text.json"));
        JSONObject jsonObject = (JSONObject) obj;

        JSONArray cells = (JSONArray) jsonObject.get("cells");
        Iterator<JSONObject> iterator = cells.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }

     } catch (Exception e) {

      e.printStackTrace();

     }

  }

}
1

Now that you have modified the question and json, here is the solution you're looking for:

public static void main(String[] args) {
    try {
        Map source = (new ObjectMapper()).readValue(new File(
                "C:\\json.txt"), Map.class);

        Map<String, Object> result = new LinkedHashMap<>();
        buildFlattenedMap(result, source, null);
        for (String s : result.keySet()) {
             System.out.println(s);
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}

private static void buildFlattenedMap(Map<String, Object> result,
        Map<String, Object> source, String path) {
    for (Map.Entry<String, Object> entry : source.entrySet()) {
        String key = entry.getKey();
        if (hasText(path)) {
            if (key.charAt(0) == '[') {
                key = StringUtils.join(path, key);
            } else {
                key = StringUtils.join(path, '.', key);
            }
        }
        Object value = entry.getValue();
        if (value instanceof String) {
            result.put(key, value);
        } else if (value instanceof Map) {
            // Need a compound key
            @SuppressWarnings("unchecked")
            Map<String, Object> map = (Map<String, Object>) value;
            buildFlattenedMap(result, map, key);
        } else if (value instanceof Collection) {
            // Need a compound key
            @SuppressWarnings("unchecked")
            Collection<Object> collection = (Collection<Object>) value;
            int count = 0;
            for (Object object : collection) {
                buildFlattenedMap(result, Collections.singletonMap("["
                        + (count++) + "]", object), key);
            }
        } else {
            result.put(key, value == null ? StringUtils.EMPTY : value);
        }
    }
}

private static boolean hasText(CharSequence str) {
    if (StringUtils.isEmpty(str)) {
        return false;
    }
    int strLen = str.length();
    for (int i = 0; i < strLen; i++) {
        if (!Character.isWhitespace(str.charAt(i))) {
            return true;
        }
    }
    return false;
}

FYI, buildFlattenedMap method is actually from spring framework which I had used recently for processing a similar stuff. https://github.com/spring-projects/spring-framework/blob/master/spring-beans/src/main/java/org/springframework/beans/factory/config/YamlProcessor.java

Pavan Kumar
  • 4,182
  • 1
  • 30
  • 45