i have a json file with many elements like these:
我有一个包含许多元素的json文件:
{
"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?
我想用gson读取该文件,但我发现的所有示例仅适用于一个元素。因此,在阅读第一个之后,抛出'预期的EOF'例外。我怎么能克服这个?
2 个解决方案
#1
3
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.
Greg是对的,这是不正确的JSON,你应该尝试生成有效的JSON,在开头是前缀“[”,最后追加“]”,并用逗号(“,”)分隔每个元素,所以它是JSON对象的JSON数组。
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.
但是,如果您无法更改格式,请将其视为“包含格式良好的JSON片段串联的字符串”。以这种方式接近它,将大字符串分解为更小的有效json字符串,并逐个解析它们。
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.
要将大字符串分成单个片段,您只需计算括号即可。使用“预解析器”将东西复制到缓冲区(StringBuilder?),每次遇到“{”时递增计数器,每次进入“}”时递减计数器,如果计数器为零通过缓冲区字符串到gson进行解析,清除缓冲区并继续执行文件的末尾。
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.
您甚至可以使用该预解析器将其转换为有效的json,只需在计数器达到零时附加“,”,并将所有内容传递给gson进行单次解析,但这可能意味着将所有内容加载到ram中,并且我不会不知道你的文件有多大。
#2
9
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.)
以下陈述不正确。 Gson没有内置功能来简单地处理这种JSON序列的反序列化。 (看评论。)
If switching JSON-to/from-Java APIs is an option, Jackson does have such a feature, as demonstrated below.
如果将JSON-to-from-Java API切换为一个选项,Jackson确实具有这样的功能,如下所示。
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.
更新:使用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));
}
}
}
#1
3
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.
Greg是对的,这是不正确的JSON,你应该尝试生成有效的JSON,在开头是前缀“[”,最后追加“]”,并用逗号(“,”)分隔每个元素,所以它是JSON对象的JSON数组。
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.
但是,如果您无法更改格式,请将其视为“包含格式良好的JSON片段串联的字符串”。以这种方式接近它,将大字符串分解为更小的有效json字符串,并逐个解析它们。
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.
要将大字符串分成单个片段,您只需计算括号即可。使用“预解析器”将东西复制到缓冲区(StringBuilder?),每次遇到“{”时递增计数器,每次进入“}”时递减计数器,如果计数器为零通过缓冲区字符串到gson进行解析,清除缓冲区并继续执行文件的末尾。
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.
您甚至可以使用该预解析器将其转换为有效的json,只需在计数器达到零时附加“,”,并将所有内容传递给gson进行单次解析,但这可能意味着将所有内容加载到ram中,并且我不会不知道你的文件有多大。
#2
9
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.)
以下陈述不正确。 Gson没有内置功能来简单地处理这种JSON序列的反序列化。 (看评论。)
If switching JSON-to/from-Java APIs is an option, Jackson does have such a feature, as demonstrated below.
如果将JSON-to-from-Java API切换为一个选项,Jackson确实具有这样的功能,如下所示。
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.
更新:使用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));
}
}
}