7

現在、入力ストリーム/リーダーを使用してかなり大きな JSONfile を解析するために GSON を使用しています。私の Android デバイスでは、解析に約 35 秒かかります。いくつかのベンチマーク テストから、Jackson のパフォーマンスがはるかに優れていることがわかりました。しかし、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

Jackson の仕組みと実装方法がよくわかりません。AndroidコードでJacksonの実装を変更して、動作し、データにアクセスできるようにする方法を知っている人はいますか?

編集:私の解決策を得ました

MHの答えの助けを借りて。私はそれを見つけることができました。私は今使用しています:

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

3 に答える 3

9

以下は、Jacksonを使用した実際の例です。元の質問のJSON(有効で、Javaデータ構造と一致するように修正)と、元のGsonの例のJavaデータ構造(@JsonPropertyGsonの代わりにJacksonを使用するように修正@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
}
于 2012-07-08T21:35:00.033 に答える
4

覚えておくべき非常に重要なことの1つは、ObjectMapperインスタンスを常に再利用したいということです。リクエストごとに1つ作成すると、処理が大幅に遅くなり、場合によっては桁違いに遅くなります。通常、静的インスタンスを1つ作成するか(作成直後に構成)、GuiceなどのDIフレームワークを介してインスタンスを注入します。

ジャクソンを使用したその他のパフォーマンスのベストプラクティスは、http ://wiki.fasterxml.com/JacksonBestPracticesPerformanceから見つけることができます。

于 2012-07-19T18:05:53.287 に答える
1

Jsonコンテンツは単なるオブジェクトのリストのようです。つまり、私の頭の上から見ると、コードは次のようになっている必要があります。

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

をラップしたり、独自のインスタンスを作成したりする必要はInputStreamありReaderませJsonFactoryJsonParser

于 2012-07-08T19:36:25.800 に答える