2012-07-08 86 views
3

我目前使用GSON使用inputstream/reader解析相當大的JSON文件。 解析需要大約35秒,在我的Android設備上,我從某些基準測試中瞭解到傑克遜的表現更好。但我無法找到如何使用傑克遜解析我的JSON文件。誰能幫我?從Gson更改爲Jackson解析JSON

我的JSON是這樣的:

[ 

    { 
     "venue": { … } 
    }, 
    { 
     "venue": { 
      "venue_seasons": [ … ], 
      "address": "the address", 
      "city": "the city", 
      "name": "the name", 
      "created_at": "2011-05-31T07:55:33Z", 
      "latitude": 00.000000, 
      "country": "the country", 
      "internal_link_en": null, 
      "internal_link_nl": null, 
      "updated_at": "2011-09-15T14:46:09Z", 
      "zipcode": "the zipcode", 
      "foursquare_link": "foursquare url", 
      "url": null, 
      "id": 3, 
      "tip": "some tip", 
      "uid": "4ab5e205f964a520317620e3", 
      "phone": "phonenr", 
      "recommended": null, 
      "website": "someurl", 
      "venue_photos": [ … ], //array containing objects with urls of images 
      "description": null, 
      "longitude": 00.000000, 
      "thumbnail_location": null, 
      "subcategories": [ … ], 
      "opening_en": null, 
      "opening_nl": null, 
      "hidden": false, 
      "twitter": "thetwitteraccount", 
      "themes": [ … ] 
     } 
    }, //more venues 
] 

我GSON代碼看起來是這樣,它的工作原理:

AssetManager assetManager = getAssets(); 
InputStream inputStream = null; 
try { 
    inputStream = assetManager.open("filename.json"); 
} catch (IOException e) { 
    Log.e("tag", e.getMessage()); 
} 

Reader reader = new InputStreamReader(inputStream); 

Gson gson = new Gson(); 
List<JsonResponse> venueList = gson.fromJson(reader, new TypeToken<List<JsonResponse>>() {}.getType()); 
JsonResponse naam = venueList.get(12); 
String denaam = naam.venue.getName; 
Log.i("nr12",denaam); 
Log.i("timetracker","stop"); 

// just some logging to test if the parser works 
for (JsonResponse venue : venueList) { 
    String tijdel = String.valueOf(venue.venue.id); 
    Log.i(venuetag,"name of venue"+ tijdel+ " is: " + venue.venue.getName); 
} 

... 

class JsonResponse 
{ 
    Venues venue; 
} 

class Venues 
{ 
    public List<VenueSeasons> venue_seasons; 

    public List<VenuePhotos> venue_photos; 

    public List<SubCategories> subcategories; 

    public List<Themes> themes; 

    @SerializedName("address") 
    public String getAdress; 

    @SerializedName("city") 
    public String getCity; 

    @SerializedName("country") 
    public String getCountry; 

    @SerializedName("name") 
    public String getName; 

    @SerializedName("created_at") 
    public Date getCreatedAt; 

    @SerializedName("updated_at") 
    public Date getUpdatedAt; 

    @SerializedName("internal_link_nl") 
    public String getInternalLinkNl; 

    @SerializedName("internal_link_en") 
    public String getInternalLinkEN; 

    @SerializedName("latitude") 
    public Double getLatitude; 

    @SerializedName("longitude") 
    public Double getLongitude; 

    @SerializedName("foursquare_link") 
    public String getFoursquareLink; 

    @SerializedName("url") 
    public String getURL; 

    @SerializedName("phone") 
    public String getPhone; 

    @SerializedName("zipcode") 
    public String getZipCode; 

    public String tip; 

    public String tip_en; 

    public String uid; 

    public int id; 

    @SerializedName("website") 
    public String getWebsite; 

    @SerializedName("recommended") 
    public Boolean getRecommended; 

    @SerializedName("description") 
    public String getDescription; 

    @SerializedName("hidden") 
    public Boolean getHidden; 

    @SerializedName("opening_en") 
    public String getOpeningEN; 

    @SerializedName("opening_nl") 
    public String getOpeningNL; 

    @SerializedName("twitter") 
    public String getTwitter; 

    @SerializedName("thumbnail_location") 
    public String getThumbnailLocation; 
} 


public class VenuePhotos 
{ 
    @SerializedName("large") 
    public String getLargePhotoURL; 

    @SerializedName("medium") 
    public String getMediumPhotoURL; 

    @SerializedName("small") 
    public String getSmallPhotoURL; 

    @SerializedName("original") 
    public String getOriginalPhotoURL; 

    public String uid; 

    public int id; 

    public int venue_id; 

    public boolean selected; 

    @SerializedName("created_at") 
    public Date getCreatedAt; 

    @SerializedName("updated_at") 
    public Date getUpdatedAt; 
} 

現在這個工作。我做了一些與數據的東西,解析後它的作品都很棒,但我認爲它吸了我的應用程序的啓動需要很長時間。

我的傑克遜碼(失敗的)是:

AssetManager assetManager = getAssets(); 
InputStream inputStream = null; 
try { 
    inputStream = assetManager.open("originalDelftJson.json"); 
} catch (IOException e) { 
    Log.e("tag", e.getMessage()); 
} 
Reader reader = new InputStreamReader(inputStream); 

ObjectMapper objectMapper = new ObjectMapper(); 
JsonFactory jsonFactory = new JsonFactory(); 
JJsonResponse response = null; 
try { 
    JsonParser jp = jsonFactory.createJsonParser(reader); 
    response = objectMapper.readValue(jp, JJsonResponse.class); 
    String test = String.valueOf(response.venue.size()); 

帶班:

public class JJsonResponse 
{ 
    public List<JVenue> venue; 
} 

class Venues 
{ 
    public List<VenueSeasons> venue_seasons; 

    public List<VenuePhotos> venue_photos; 

    public List<SubCategories> subcategories; 

    public List<Themes> themes; 

    @SerializedName("address") 
    public String getAdress; 

    @SerializedName("city") 
    public String getCity; 

    @SerializedName("country") 
    public String getCountry; 

    @SerializedName("name") 
    public String getName; 

    @SerializedName("created_at") 
    public Date getCreatedAt; 

    @SerializedName("updated_at") 
    public Date getUpdatedAt; 

    @SerializedName("internal_link_nl") 
    public String getInternalLinkNl; 

    @SerializedName("internal_link_en") 
    public String getInternalLinkEN; 

    @SerializedName("latitude") 
    public Double getLatitude; 

    @SerializedName("longitude") 
    public Double getLongitude; 

    @SerializedName("foursquare_link") 
    public String getFoursquareLink; 

    @SerializedName("url") 
    public String getURL; 

    @SerializedName("phone") 
    public String getPhone; 

    @SerializedName("zipcode") 
    public String getZipCode; 

    public String tip; 

    public String tip_en; 

    public String uid; 

    public int id; 

    @SerializedName("website") 
    public String getWebsite; 

    @SerializedName("recommended") 
    public Boolean getRecommended; 

    @SerializedName("description") 
    public String getDescription; 

    @SerializedName("hidden") 
    public Boolean getHidden; 

    @SerializedName("opening_en") 
    public String getOpeningEN; 

    @SerializedName("opening_nl") 
    public String getOpeningNL; 

    @SerializedName("twitter") 
    public String getTwitter; 

    @SerializedName("thumbnail_location") 
    public String getThumbnailLocation; 
} 

public class JVenue 
{ 
    public String name; 
    public int id; 
    public String city; 
    public String address; 
    public String country; 
    public String internal_link_nl; 
    public String internal_link_en; 
    public String zipcode; 
    public String foursquare_link; 
    public String tip_en; 
    public String url; 
    public Date created_at; 
    public Date updated_at; 
    public float latitude; 
    public float longitude; 
    public String tip; 
    public String uid; 
    public String phone; 
    public String recommended; 
    public String website; 
    public String description; 
    public String thumbnail_location; 
    public boolean hidden; 
    public String twitter; 
    public String opening_en; 
    public String opening_nl; 
} 

我覺得我很接近,但即時通訊做錯了什麼,因爲我得到的錯誤:org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of com.jacksonrecipes.testapp.model.JJsonResponse out of START_ARRAY token

我真的不明白傑克遜的工作方式以及如何實施它。有誰知道如何在我的Android代碼中更改我的傑克遜實現,以便它可以工作,並且我可以訪問數據?

編輯:有我的解決方案

隨着MH的答案的幫助。我可以找到它。我現在使用:

List<JJsonResponse> venueCounter = objectMapper.readValue(inputStream, new TypeReference<List<JJsonResponse>>() { }); 
+0

哪個版本GSON的使用是你?我是一名Gson開發人員,我很樂意讓您的代碼更快運行。如果您可以給我一份完整文檔的副本,我們可以將其作爲我們的標準基準之一。 – 2012-07-09 03:59:10

+0

快速提問:是否加快了處理速度?由於較大的罐子尺寸,啓動時間可能會較長。 – StaxMan 2012-07-09 17:48:30

+0

@StaxMan是的,但沒有我希望的那麼多。傑克遜在這種情況下快了大約20%,仍然試圖更好地優化它。使用更快的android設備,現在可以接受啓動時間。 – Jasper 2012-07-19 09:15:59

回答

1

它看起來像你的Json內容只是一個對象列表。這意味着,從我的頭頂,你的代碼將需要看起來像這樣:

List<JVenue> venues = mapper.readValue(inputStream, new TypeReference<List<JVenue>>() { }); 

沒有必要來包裝InputStreamReader或創建自己的JsonFactoryJsonParser實例。

+0

工作;以及得到一個數組:'JVenue [] venues = mapper.readValue(inputStream,JVenue []。class);' – StaxMan 2012-07-09 17:47:36

5

以下是使用Jackson原始問題(使用原始問題中的JSON(更正爲有效且與Java數據結構匹配))與原始Gson示例中的Java數據結構(更正爲使用Jackson的@JsonProperty代替Gson的@SerializedName)。

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

import java.io.File; 
import java.util.Date; 
import java.util.List; 

import com.fasterxml.jackson.annotation.JsonProperty; 
import com.fasterxml.jackson.core.type.TypeReference; 
import com.fasterxml.jackson.databind.ObjectMapper; 

public class JacksonFoo 
{ 
    public static void main(String[] args) throws Exception 
    { 
    ObjectMapper mapper = new ObjectMapper().setVisibility(FIELD, ANY); 
    List<JsonResponse> responses = mapper.readValue(new File("input.json"), new TypeReference<List<JsonResponse>>() {}); 
    System.out.println(responses); 
    System.out.println(mapper.writeValueAsString(responses)); 
    } 
} 

class JsonResponse 
{ 
    Venues venue; 

    @Override 
    public String toString() 
    { 
    return venue.toString(); 
    } 
} 

class Venues 
{ 
    List<VenueSeasons> venue_seasons; 
    @JsonProperty("address") String getAdress; 
    @JsonProperty("city") String getCity; 
    @JsonProperty("name") String getName; 
    @JsonProperty("created_at") Date getCreatedAt; 
    @JsonProperty("latitude") Double getLatitude; 
    @JsonProperty("country") String getCountry; 
    @JsonProperty("internal_link_en") String getInternalLinkEN; 
    @JsonProperty("internal_link_nl") String getInternalLinkNl; 
    @JsonProperty("updated_at") Date getUpdatedAt; 
    @JsonProperty("zipcode") String getZipCode; 
    @JsonProperty("foursquare_link") String getFoursquareLink; 
    @JsonProperty("url") String getURL; 
    int id; 
    String tip; 
    String uid; 
    @JsonProperty("phone") String getPhone; 
    @JsonProperty("recommended") Boolean getRecommended; 
    @JsonProperty("website") String getWebsite; 
    List<VenuePhotos> venue_photos; 
    @JsonProperty("description") String getDescription; 
    @JsonProperty("longitude") Double getLongitude; 
    @JsonProperty("thumbnail_location") String getThumbnailLocation; 
    List<SubCategories> subcategories; 
    @JsonProperty("opening_en") String getOpeningEN; 
    @JsonProperty("opening_nl") String getOpeningNL; 
    @JsonProperty("hidden") Boolean getHidden; 
    @JsonProperty("twitter") String getTwitter; 
    List<Themes> themes; 
    String tip_en; // not in example JSON 

    @Override 
    public String toString() 
    { 
    return String.format("Venues: id=%d", id); 
    } 
} 

class VenuePhotos 
{ 
    @JsonProperty("large") String getLargePhotoURL; 
    @JsonProperty("medium") String getMediumPhotoURL; 
    @JsonProperty("small") String getSmallPhotoURL; 
    @JsonProperty("original") String getOriginalPhotoURL; 
    String uid; 
    int id; 
    int venue_id; 
    boolean selected; 
    @JsonProperty("created_at") Date getCreatedAt; 
    @JsonProperty("updated_at") Date getUpdatedAt; 
} 

enum VenueSeasons 
{ 
    Spring, Summer, Fall, Winter 
} 

enum SubCategories 
{ 
    SubCat1, SubCat2, SubCat3, SubCat4 
} 

enum Themes 
{ 
    Theme1, Theme2, Theme3, Theme4 
} 
4

一個非常重要的一點要記住的是,你總是要重用ObjectMapper實例 - 在創建每個請求一個會減慢速度了很多,可能是由一個數量級。通常只需創建一個靜態實例(在創建後立即配置),或者通過像Guice這樣的DI框架注入一個靜態實例。

其他性能與最佳實踐傑克遜可以發現:http://wiki.fasterxml.com/JacksonBestPracticesPerformance