Recursive parsing json file using Jackson Json parser

I am trying to recursively parse a sample Json file that contains many sets of complex elements. And the code I'm trying is like this:

public class Jsonex { public static void main(String argv[]) { try { Jsonex jsonExample = new Jsonex(); jsonExample.testJackson(); } catch (Exception e){ System.out.println("Exception " + e); } } public static void testJackson() throws IOException { JsonFactory factory = new JsonFactory(); // System.out.println("hello"); ObjectMapper mapper = new ObjectMapper(factory); File from = new File("D://albumList.txt"); TypeReference<HashMap<String,Object>> typeRef = new TypeReference<HashMap<String,Object>>() {}; HashMap<String,Object> o= mapper.readValue(from, typeRef); // System.out.println("" + o); Iterator it = o.entrySet().iterator(); while (it.hasNext()) { Map.Entry pairs = (Map.Entry)it.next(); System.out.println(pairs.getKey() + " = " + pairs.getValue()); HashMap<String,Object> o1=mapper.readValue(pairs.getValue().toString(),typeRef); System.out.println("hey"+o1); Iterator it1 = o1.entrySet().iterator(); while (it1.hasNext()) { Map.Entry pairs1 = (Map.Entry)it.next(); System.out.println(pairs1.getKey() + " = " + pairs1.getValue()); it1.remove(); // avoids a ConcurrentModificat } } }} 

and I get this exception:

Exception org.codehaus.jackson.JsonParseException: Unexpected character ('i' (code 105)): expected a double quote to start the field name in [Source: java.io.StringReader@2de7753a ; row: 1, column: 3]

In fact, what I'm trying to do is parse the file and get a list of pairs of object names and take an object from which inturn has name-object pairs. - but the problem is that the parser expects a "" before the lines!

+4
source share
3 answers

Instead of disassembling everything yourself, you should consider using the built-in Jacksons tree model function ( http://wiki.fasterxml.com/JacksonTreeModel ):

 ObjectMapper mapper = new ObjectMapper(factory); File from = new File("D://albumList.txt"); JsonNode rootNode = mapper.readTree(from); Iterator<Map.Entry<String,JsonNode>> fields = rootNode.fields(); while (fields.hasNext()) { Map.Entry<String,JsonNode> field = fields.next(); System.out.println(field.getKey() + " = " + field.getValue()); … } 

This should be more convenient in the long run. Check out the API at http://fasterxml.github.com/jackson-databind/javadoc/2.1.0/com/fasterxml/jackson/databind/JsonNode.html .

+5
source

Just a comment. As you know, there are 3 main processing modes supported by Jackson (data binding, stream API and tree model). You should take into account that if you decide to use the Tree Model, according to official documents, memory usage is proportional to the display of content (similar to data binding), so tree models can NOT be used with huge Json content if mapping is performed at the same time. This is the same problem as data binding; and sometimes the solution is to use Stream-of-Events.

+4
source

While developing how to dynamically parse JSON in HashMaps and ArrayLists today in high demand scenario, I came across ObjectMapper answer here.

I'm not sure what the internal devices do, but I found that it is on average about 20 times slower for my use case than a simple recursive analysis method that uses only jackson-core . Perhaps I am missing something else that the library picks up?

For reference, this is with jackson-core-2.9.9 running on Windows Server 2016, OpenJDK Java 11:

 //test method public static void main(String[] args) throws JsonParseException, IOException { String json = "{\"string1\":\"string1\",\"obj\":{\"objNest\":{\"string3\":\"string3\"}}," + "\"objArray\":[{\"string4\":\"string4\",\"int1\":1,\"float1\":1.2345,\"boolean\":true}," + "{\"string5\":\"string5\",\"int2\":2,\"float2\":6.7890,\"boolean\":true}]," + "\"null\":null,\"array\":[\"1234\\\"testeroo\\\"567890\",\"9876543210\"]," + "\"boolean2\":false}"; System.out.println(json); // using the ObjectMapper method... long startTime1 = System.currentTimeMillis(); ObjectMapper mapper = new ObjectMapper(); for (int i = 0; i < 100; i++) { HashMap<String,Object> map = new HashMap<String,Object>(); map = mapper.readValue(json, HashMap.class); } long endTime1 = System.currentTimeMillis(); System.out.println("Total execution time: " + (endTime1-startTime1) + "ms"); // just using the jackson-core parsing... long startTime2 = System.currentTimeMillis(); JsonFactory factory = new JsonFactory(); for (int i = 0; i < 100; i++) { HashMap<String,Object> map = new HashMap<String,Object>(); JsonParser parser = factory.createParser(json); JsonToken token = parser.nextToken(); map = coreParser(map, parser, token); } long endTime2 = System.currentTimeMillis(); System.out.println("Total execution time: " + (endTime2-startTime2) + "ms"); } 

Execution 1

ObjectMapper: 1042ms

Kernel: 54 ms

19.29 times faster

Execution 2

ObjectMapper: 760ms

Kernel: 40 ms

19.00 times faster

Execution 3

ObjectMapper: 1000 ms

Core: 45 ms

22.22 times faster

Execution 4

ObjectMapper: 953ms

Kernel: 52 ms

18.32 times faster

Execution 5

ObjectMapper: 1017ms

Kernel: 54 ms

18.83 times faster

19.53 times faster on average

I recursively dealt with this:

 private static HashMap<String,Object> parse(HashMap<String,Object> map, JsonParser parser, JsonToken token) throws IOException { String field = ""; token = parser.nextToken(); while(!token.equals(JsonToken.END_OBJECT)) { if (token != null) { switch (token) { case FIELD_NAME: field = parser.getCurrentName(); break; case VALUE_STRING: map.put(field, parser.getValueAsString()); break; case VALUE_NUMBER_INT: map.put(field, parser.getValueAsInt()); break; case VALUE_NUMBER_FLOAT: map.put(field, parser.getValueAsDouble()); break; case VALUE_TRUE: map.put(field, parser.getValueAsBoolean()); break; case VALUE_FALSE: map.put(field, parser.getValueAsBoolean()); break; case VALUE_NULL: map.put(field, null); break; case START_OBJECT: HashMap<String,Object> objMap = new HashMap<String,Object>(); map.put(field, parse(objMap, parser, token)); break; case START_ARRAY: ArrayList<Object> arrayList = new ArrayList<Object>(); token = parser.nextToken(); while (!token.equals(JsonToken.END_ARRAY)) { if (token.equals(JsonToken.START_OBJECT)) { HashMap<String,Object> arrayMap = new HashMap<String,Object>(); arrayList.add(parse(arrayMap, parser, token)); } else { arrayList.add(parser.getValueAsString()); } token = parser.nextToken(); } map.put(field, arrayList); break; default: break; } } token = parser.nextToken(); } return map; } 
+1
source

All Articles