Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading multiple elements from json file

i have a json file with many elements like these:

{ 
"code" : "hfuiew89", 
"type" : "location", 
"coordinates" : [ { "lat" : 40.9861, "lon" : 29.1046, "index" : 1 }, 
          { "lat" : 40.9976, "lon" : 29.1153, "index" : 2 }, 
          { "lat" : 40.9809, "lon" : 29.2194, "index" : 3 }] 
}
{ 
"code" : "klsdsjh", 
"type" : "location", 
"relatedTags" : [ "kolmha" ], 
"coordinates" : [ { "lat" : 40.9808, "lon" : 29.1605, "index" : 1 }, 
              { "lat" : 40.9965, "lon" : 29.1672, "index" : 2 }] 
}

i want to read that file with gson but all examples i found are only for one element. therefore after reading the first one, throws 'Expected EOF' exception. how can i overcome this?

like image 755
eblek Avatar asked Jun 28 '12 21:06

eblek


2 Answers

For what it's worth...

The following statement is incorrect. Gson does not have a built in feature to simply handle deserialization of such a JSON sequence. (See comments.)

If switching JSON-to/from-Java APIs is an option, Jackson does have such a feature, as demonstrated below.

input.json

{
"name":"A"
}
{
"name":"B"
}

JacksonFoo.java

import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY;
import static com.fasterxml.jackson.annotation.PropertyAccessor.FIELD;

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

import com.fasterxml.jackson.databind.ObjectMapper;

public class JacksonFoo
{
  public static void main(String[] args) throws Exception
  {
    ObjectMapper mapper = new ObjectMapper().setVisibility(FIELD, ANY);
    Iterator<Thing> thingsIterator = mapper.reader(Thing.class).readValues(new File("input.json"));
    while (thingsIterator.hasNext())
    {
      System.out.println(thingsIterator.next());
    }
  }
}

class Thing
{
  private String name;

  @Override
  public String toString()
  {
    return String.format("Thing: name=%s", name);
  }
}

Output:

Thing: name=A
Thing: name=B

Update: A similar solution using Gson.

GsonFoo.java

import java.io.FileReader;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonStreamParser;

public class GsonFoo
{
  public static void main(String[] args) throws Exception
  {
    Gson gson = new GsonBuilder().create();

    JsonStreamParser parser = new JsonStreamParser(new FileReader("input.json"));
    while(parser.hasNext())
    {
      System.out.println(gson.fromJson(parser.next(), Thing.class));
    }
  }
}
like image 186
Programmer Bruce Avatar answered Oct 06 '22 03:10

Programmer Bruce


Greg is right, this is incorrect JSON, and you should try to generate valid JSON, that is prepend "[" at the beginning, append "]" at the end, and separate each element with a comma (","), so that it is a JSON array of JSON object.

However, if you cannot change the format you have, consider it "a string containing a concatenation of well formed JSON fragments". Approaching it that way, break the big string into smaller, valid json strings, and parse them one by one.

To break the big string into single fragments you can simply count the brackets. With a "pre-parser" that copies stuff into a buffer (a StringBuilder?), increments a counter each time it encounters a "{", decreases it each time it enouters a "}", and if the counter is at zero pass the buffer string to gson for parsing, clear the buffer and go on to the end of the file.

You can even use that pre-parser to convert it to valid json, simply appending a "," when the counter reaches zero, and the passing everything to gson for a single parsing, but that could mean loading everything into ram, and I don't know how big your file is.

like image 38
Simone Gianni Avatar answered Oct 06 '22 03:10

Simone Gianni