2012-07-08 41 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