2012-06-28 42 views
5

tôi có một tệp json với nhiều yếu tố như thế này:Đọc nhiều yếu tố từ tệp 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 }] 
} 

tôi muốn đọc tập tin đó với gson nhưng tất cả những ví dụ tôi tìm thấy chỉ là một yếu tố. do đó sau khi đọc bài đầu tiên, hãy ném ngoại lệ 'Mong đợi EOF'. làm thế nào tôi có thể vượt qua điều này?

+2

JSON được * có nghĩa là * trở thành một thực thể duy nhất (thể là một đối tượng, hoặc một mảng) - và những gì bạn đã có được nhiều đối tượng. Những gì bạn thực sự muốn trong tình huống này là một mảng ở cấp cao nhất, với mỗi đối tượng như là một phần tử trong nó. Bạn có thể ảnh hưởng đến thế hệ * của JSON này hay bạn bị kẹt với định dạng này? –

Trả lời

3

Greg là đúng, đây là JSON không chính xác và bạn nên cố gắng tạo JSON hợp lệ, tức là thêm "[" ở đầu, nối "]" ở cuối và tách từng phần tử bằng dấu phẩy (", "), để nó là một mảng JSON của đối tượng JSON.

Tuy nhiên, nếu bạn không thể thay đổi định dạng mình có, hãy xem xét "chuỗi có chứa một đoạn ghép các đoạn JSON được tạo thành tốt". Tiếp cận nó theo cách đó, phá vỡ chuỗi lớn thành các chuỗi json nhỏ hơn, hợp lệ và phân tích từng chuỗi một.

Để chia chuỗi lớn thành từng đoạn, bạn có thể chỉ cần đếm dấu ngoặc đơn. Với một "phân tích cú pháp" sao chép nội dung vào một bộ đệm (một StringBuilder?), Tăng một bộ đếm mỗi khi nó gặp "{", giảm nó mỗi lần nó "" xuất hiện, và nếu bộ đếm ở mức 0 chuỗi bộ đệm để gson để phân tích cú pháp, xóa bộ đệm và tiếp tục đến cuối tệp. Bạn thậm chí có thể sử dụng trình phân tích cú pháp trước đó để chuyển đổi nó thành json hợp lệ, chỉ cần thêm "," khi bộ đếm đạt đến 0 và chuyển mọi thứ thành gson để phân tích cú pháp đơn, nhưng điều đó có nghĩa là tải mọi thứ vào ram và tôi không biết tệp của bạn lớn tới mức nào.

+0

Đi cùng với điều này, bạn chỉ có thể tạo tệp của mình dưới dạng một mảng các đối tượng JSON. Tuy nhiên bạn có thể gặp vấn đề về bộ nhớ nếu có quá nhiều thực thể trong mảng.Nếu không, một chuỗi các thực thể JSON được phân tách sẽ tốt hơn và cho phép bạn chỉ tải một phần của tệp tại một thời điểm. – Drizzt321

+0

Vâng, đó là những gì tôi đã cố gắng để thể hiện: một tập tin lớn json mảng, và một cuộc gọi duy nhất cho phân tích cú pháp, có vẻ dễ dàng hơn, nhưng cũng có thể có nghĩa là tải tất cả mọi thứ trong ram; trong khi đi "từng bước", bạn có thể cho phép xử lý từng thực thể ... đây là SAX chống lại DOM một lần nữa, nhưng bây giờ nó được gọi là JSON nó làm cho nó âm thanh nhiều hơn nữa k00l. –

+0

Haha, đúng vậy. Mặc dù JSON có vẻ ít tiết hơn (không có thẻ đóng) và cũng cung cấp một phương tiện rất dễ dàng để chuyển dữ liệu sang Javascript, đây là một trong những lý do cho sự gia tăng lớn của JSON. – Drizzt321

9

Đối với giá trị của nó ...

Tuyên bố sau không chính xác. Gson không có một tính năng tích hợp để chỉ đơn giản là xử lý deserialization của một chuỗi JSON như vậy. (Xem ý kiến.)

Nếu chuyển đổi JSON-sang/từ-Java API là một tùy chọn, Jackson không có tính năng như được minh họa dưới đây.

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 

Cập nhật: Giải pháp tương tự bằng 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)); 
    } 
    } 
} 
+2

Bài đăng này không chính xác. Gson có tính năng (sai) đó. Nó được gọi là JsonStreamParser và tài liệu có tại đây: http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/JsonStreamParser.html –

+0

Ah, gọn gàng. Tôi đã bị ném bởi việc sử dụng từ "Stream" trong API GSON. Tôi chỉ giả định "Luồng" được gọi là phân tích cú pháp JSON một mã thông báo phát trực tuyến tại một thời điểm, trái ngược với việc liên kết dữ liệu JSON với các đối tượng/mảng. –

+0

Đã cập nhật câu trả lời cho phù hợp. –

Các vấn đề liên quan