【问题标题】:Retrofit Gson LinkedTreeMap to custom object将 Gson LinkedTreeMap 改造为自定义对象
【发布时间】:2017-04-21 06:59:31
【问题描述】:

我有以下 JSON 文件:

https://www.mediamarkt.de/de/product/productlistajax.json?categoryId=563612&sort=topseller&lazyLoading=true

编辑:如果上面的链接不起作用:https://pastebin.com/cTxp1RZ6

到目前为止,我发现获取此 JSON 的唯一可能性是使用 Map:

Call<Map<String, Object>> call = liveApi.loadProductList(request.categoryId, request.sort, request.lazyLoading)

call.enqueue(new Callback<Map<String, Object>>() {
    @Override
    public void onResponse(Call<Map<String, Object>> call, Response<Map<String, Object>> response) {
        Call<Map<String, Object> map = response.body();
    }
});

但是我需要通过按键找到较低层内的所有对象。我很想用@SerializedName() 将这些对象映射到我的模型类,我该怎么做?

【问题讨论】:

  • 上面的链接坏了。你能发布 JSON 文档吗?
  • 我尝试了来自两个不同网络的链接,它对我有用。不过我会把它粘贴到一些地方
  • 刚刚也添加了一个 pastebin 链接
  • 您是否尝试过这里非常流行的自动映射生成器,例如 jsonschema2pojo.org?当 JSON 设计得不是很好时,它可能会在某些情况下失败,但值得一试。
  • 不,我没有。谢谢提示,我试试看

标签: json gson retrofit


【解决方案1】:

您所要做的就是创建自定义映射。由于您的 JSON 文档非常复杂,您可以尝试自动映射生成器,但如果它们因任何原因(动态属性、多态值、不正确的 camelCaseNaming 检测等)失败,您始终可以创建自定义映射:

final class Response {

    @SerializedName("categories") final List<Category> categories = null;
    @SerializedName("facettes") final List<Facet> facettes = null;
    @SerializedName("productlistentries") final List<Map<String, Product>> productListEntries = null;
    @SerializedName("last") final boolean isLast = Boolean.valueOf(false);

}

final class Category {

    @SerializedName("amount") final int amount = Integer.valueOf(0);

}

final class Facet {

    // ???

}

final class Product {

    @SerializedName("name") final String name = null;
    @SerializedName("modelNumber") final int modelNumber = Integer.valueOf(0);
    @SerializedName("brandLogo") final String brandLogo = null;
    @SerializedName("detailLink") final String detailLink = null;
    @SerializedName("online") final boolean isOnline = Boolean.valueOf(false);
    @SerializedName("imageURL") final String imageUrl = null;
    @SerializedName("addToBasketUrl") final String addToBasketUrl = null;
    @SerializedName("rating") final int rating = Integer.valueOf(0);
    @SerializedName("ratingCount") final int ratingCount = Integer.valueOf(0);
    @SerializedName("features") final List<Feature> features = null;
    @SerializedName("price") final String price = null;
    @SerializedName("vatLabel") final String vatLabel = null;
    @SerializedName("fees") final List<Fee> fees = null;
    @SerializedName("gtm") final Gtm gtm = null;
    @SerializedName("productComparison") final ProductComparison productComparison = null;
    @SerializedName("productWishlist") final ProductWishlist productWishlist = null;
    @SerializedName("clubProduct") final boolean isClubProduct = Boolean.valueOf(false);
    @SerializedName("onlineOnlyProduct") final boolean isOnlineOnlyProduct = Boolean.valueOf(false);

}

final class Feature {

    @SerializedName("key") final String key = null;
    @SerializedName("value") final String value = null;

}

final class Fee {

    @SerializedName("value") final String value = null;
    @SerializedName("dataLayer") final String dataLayer = null;

}

final class Gtm {

    @SerializedName("name") final String name = null;
    @SerializedName("id") final String id = null;
    @SerializedName("price") final String price = null;
    @SerializedName("brand") final String brand = null;
    @SerializedName("category") final String category = null;
    @SerializedName("dimension9") final String dimension9 = null;
    @SerializedName("dimension10") final String dimension10 = null;

}

final class ProductComparison {

    @SerializedName("dataLayer") final String dataLayer = null;
    @SerializedName("dataUrl") final String dataUrl = null;
    @SerializedName("text") final String text = null;
    @SerializedName("additionalClasses") final String additionalClasses = null;

}

final class ProductWishlist {

    @SerializedName("requestUrl") final String requestUrl = null;
    @SerializedName("text") final String text = null;

}

手工编写映射大约需要 15 分钟,因此可能有错误或拼写错误。请注意,我假设您的响应是只读的,不应该手动创建以发送到其他地方,因此所有字段都声明为final。关于原始字段的一个评论:如果您使用0false,那么Java 编译器可以内联已知编译时常量,所以Type.value(...) 是一种欺骗,让javac 认为它是一个运行时值不能内联。 (您可能想要生成 getter,但恕我直言,简单数据包的字段更易于使用并且添加的噪音更少)。

您只需将Call&lt;Map&lt;String, Object&gt;&gt; 更改为Call&lt;Response&gt;

普通 Java 中的示例,而不是 Retrofit:

try ( final Reader reader = getPackageResourceReader(Q43535942.class, "response.json") ) {
    final Response response = gson.fromJson(reader, Response.class);
    System.out.println(response.productListEntries.get(1).get("3486143").imageUrl);
}

输出:

//picscdn.redblue.de/doi/pixelboxx-mss-70874441/mobile_220_310_png/CRUNCH-GTO-4125-Verst%C3%A4rker-%28Class-D%29

【讨论】:

  • 工作就像一个魅力,Repsonse 类是我所缺少的东西
猜你喜欢
  • 1970-01-01
  • 2016-10-29
  • 2014-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多