【问题标题】:Custom deserializer or different class design Retrofit自定义解串器或不同类设计改造
【发布时间】:2015-06-16 18:50:00
【问题描述】:

对于像我这样的菜鸟来说,改造让事情变得如此简单。但是,我为当前项目请求的 API 响应结构与我之前使用的格式不同。我不确定是否需要重写我的 POJO 或在 GSON 中制作自定义反序列化器。我无法更改 JSON 结构,而且自定义反序列化器对我来说似乎令人生畏。

这是 JSON:

        {
    "Green Shirt": [
        {
            "id": "740",
            "name": “Nice Green Shirt",
            "quantity": "0",
            "make": "",
            "model": "",
            "price": “15.00",
            "size": "XXS",
            "sku": null,
            "image": "https:\/\/google.com\/green_shirt.jpg",
            "new_record": false,
            "category_name": "",
            "bar_code": "",
        },
        {
            "id": "743",
            "name": "Green Shirt",
            "quantity": “68",
            "make": "",
            "model": "",
            "price": “20.00",
            "size": "XS",
            "sku": null,
            "image": "https:\/\/google.com\/green_shirt.jpg",
            "new_record": false,
            "category_name": "",
            "bar_code": "",
        }
    ],
    "Dark Blue Jeans": [
        {
            "id": "1588",
            "name": "Dark Blue Jeans",
            "quantity": "0",
            "make": "",
            "model": "",
            "price": "0.00",
            "size": “S",
            "sku": null,
            "image": "https:\/\/google.com\/dark_blue_jeans.jpg",
            "new_record": false,
            "category_name": "",
            "bar_code": "",
            "category": null
        },
        {
            "id": "1559",
            "name": "Dark Blue Jeans",
            "quantity": "4",
            "make": "",
            "model": "",
            "price": "0.00",
            "size": “XL",
            "sku": null,
            "image": "https:\/\/google.com\/dark_blue_jeans.jpg",
            "new_record": false,
            "category_name": "",
            "bar_code": "",
            "category": null
        }
    ],
    "White Belt": [
        {
            "id": "1536",
            "name": "White Belt",
            "quantity": "37",
            "make": "",
            "model": "",
            "price": "0.00",
            "size": "One Size",
            "sku": null,
            "image": "https:\/\/google.com\/white_belt.jpg",
            "new_record": false,
            "category_name": "",
            "bar_code": "",
            "category": null
        }
    ]
}

这里是 POJO:

    public class Product
{
    private String model;

    private String bar_code;

    private String image;

    private null sku;

    private String new_record;

    private String size;

    private String id;

    private null category;

    private String price;

    private String category_name;

    private String name;

    private String quantity;

    private String make;

    public String getModel ()
    {
        return model;
    }

    public void setModel (String model)
    {
        this.model = model;
    }

    public String getBar_code ()
    {
        return bar_code;
    }

    public void setBar_code (String bar_code)
    {
        this.bar_code = bar_code;
    }

    public String getImage ()
    {
        return image;
    }

    public void setImage (String image)
    {
        this.image = image;
    }

    public null getSku ()
    {
        return sku;
    }

    public void setSku (null sku)
    {
        this.sku = sku;
    }

    public String getNew_record ()
    {
        return new_record;
    }

    public void setNew_record (String new_record)
    {
        this.new_record = new_record;
    }

    public String getSize ()
    {
        return size;
    }

    public void setSize (String size)
    {
        this.size = size;
    }

    public String getId ()
    {
        return id;
    }

    public void setId (String id)
    {
        this.id = id;
    }

    public null getCategory ()
    {
        return category;
    }

    public void setCategory (null category)
    {
        this.category = category;
    }

    public String getPrice ()
    {
        return price;
    }

    public void setPrice (String price)
    {
        this.price = price;
    }

    public String getCategory_name ()
    {
        return category_name;
    }

    public void setCategory_name (String category_name)
    {
        this.category_name = category_name;
    }

    public String getName ()
    {
        return name;
    }

    public void setName (String name)
    {
        this.name = name;
    }

    public String getQuantity ()
    {
        return quantity;
    }

    public void setQuantity (String quantity)
    {
        this.quantity = quantity;
    }

    public String getMake ()
    {
        return make;
    }

    public void setMake (String make)
    {
        this.make = make;
    }

    @Override
    public String toString()
    {
        return "ClassPojo [model = "+model+", bar_code = "+bar_code+", image = "+image+", sku = "+sku+", new_record = "+new_record+", size = "+size+", id = "+id+", category = "+category+", price = "+price+", category_name = "+category_name+", name = "+name+", quantity = "+quantity+", make = "+make+"]";
    }
}

这里是request和Retrofit接口:

    public static void requestData(String username,String password) {

        RestAdapter.Builder builder = new RestAdapter.Builder()
                .setClient(new OkClient(new OkHttpClient()))
                .setEndpoint(ENDPOINT);

        if (username != null && password != null) {
            // concatenate username and password with colon for authentication
            final String credentials = username + ":" + password;

            builder.setRequestInterceptor(new RequestInterceptor() {
                @Override
                public void intercept(RequestFacade request) {
                    // create Base64 encodet string
                    String string = "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
                    request.addHeader("Accept", "application/json");
                    request.addHeader("Authorization", string);
                }
            });
        }
        RestAdapter adapter = builder.build();


        ProductAPI api = adapter.create(ProductAPI.class);

        api.getInventory(new Callback<List<Product>>() {
            @Override
            public void success(List<Product> products, Response response) {
                Log.d(TAG, response.getUrl());
                Log.d(TAG, response.getReason());
                mInventory = product;
            }
            @Override
            public void failure(RetrofitError error) {
                Log.d(TAG,error.getMessage());
            }
        });
    }

public interface ProductAPI {
    @GET("/v2/get-inventory")
    public void getInventory(Callback<List<Product>> response);
}

这是我得到的错误,因为 JSON 以“{”而不是“[”开头 com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: 应为 BEGIN_ARRAY,但在第 1 行第 2 列路径 $

处为 BEGIN_OBJECT

【问题讨论】:

    标签: java android gson deserialization retrofit


    【解决方案1】:

    您的 JSON 无效,请先尝试正确格式化,然后再执行其他操作。

    格式正确:

    {
      "Green Shirt": [
        {
          "id": "740",
          "name": "Nice Green Shirt",
          "quantity": "0",
          "make": "",
          "model": "",
          "price": "15.00",
          "size": "XXS",
          "sku": null,
          "image": "https:\\/\\/google.com\\/green_shirt.jpg",
          "new_record": false,
          "category_name": "",
          "bar_code": ""
        },
        {
          "id": "743",
          "name": "Green Shirt",
          "quantity": "68",
          "make": "",
          "model": "",
          "price": "20.00",
          "size": "XS",
          "sku": null,
          "image": "https:\\/\\/google.com\\/green_shirt.jpg",
          "new_record": false,
          "category_name": "",
          "bar_code": ""
        }
      ],
      "Dark Blue Jeans": [
        {
          "id": "1588",
          "name": "Dark Blue Jeans",
          "quantity": "0",
          "make": "",
          "model": "",
          "price": "0.00",
          "size": "S",
          "sku": null,
          "image": "https:\\/\\/google.com\\/dark_blue_jeans.jpg",
          "new_record": false,
          "category_name": "",
          "bar_code": "",
          "category": null
        },
        {
          "id": "1559",
          "name": "Dark Blue Jeans",
          "quantity": "4",
          "make": "",
          "model": "",
          "price": "0.00",
          "size": "XL",
          "sku": null,
          "image": "https:\\/\\/google.com\\/dark_blue_jeans.jpg",
          "new_record": false,
          "category_name": "",
          "bar_code": "",
          "category": null
        }
      ],
      "White Belt": [
        {
          "id": "1536",
          "name": "White Belt",
          "quantity": "37",
          "make": "",
          "model": "",
          "price": "0.00",
          "size": "One Size",
          "sku": null,
          "image": "https:\\/\\/google.com\\/white_belt.jpg",
          "new_record": false,
          "category_name": "",
          "bar_code": "",
          "category": null
        }
      ]
    }
    

    它有一些错误:

    Error:Strings should be wrapped in double quotes.[Code 17, Structure 12]
    Error:Strings should be wrapped in double quotes.[Code 17, Structure 28]
    Error:Invalid comma, expecting }.[Code 141, Structure 53]
    Error:Expecting string, not }.[Code 8, Structure 54]
    Error:Strings should be wrapped in double quotes.[Code 17, Structure 67]
    Error:Strings should be wrapped in double quotes.[Code 17, Structure 79]
    Error:Invalid comma, expecting }.[Code 141, Structure 104]
    Error:Expecting string, not }.[Code 8, Structure 105]
    Error:Strings should be wrapped in double quotes.[Code 17, Structure 138]
    Error:Strings should be wrapped in double quotes.[Code 17, Structure 192]
    

    【讨论】:

      【解决方案2】:

      问题似乎正是它所说的。响应是一个有数组的对象,而不是直接的数组:

      { [{},{},{}] }
      

      如果响应是:

      [{},{},{}]
      

      它会起作用,但由于您无法更改响应格式,您应该更改您的 java.lang.您应该有一个包含产品列表的对象,而不是期望产品列表。这就是改造将如何映射它。

      编辑:
      响应其实是这样的:

       {[],[],[]}
      

      不是列表,是由三个对象列表组成的对象产品

      到对象的映射必须是:

      public class Wrapper
      {
         List<Product> WhiteBelt;
         List<Product> DarkBlueJeans;
         List<Product> GreenShirt;
      
      }
      

      类似的东西就是你的结构。我认为这是不对的,因为您通常想要一个列表,而不是“硬编码”内包含三个列表的对象。

      如果有帮助请告诉我

      已编辑:

      所以你需要这样的东西:

      {
          "products":
           [{ "name" : "Green Shirt"
              "items":
               [{"id": "740",
                 "name": “Nice Green Shirt",
                 "quantity": "0",
                 "make": "",
                 "model": "",
                 "price": “15.00",
                 "size": "XXS",
                 "sku": null,
                 "image": "https:\/\/google.com\/green_shirt.jpg",
                 "new_record": false,
                 "category_name": "",
                 "bar_code": ""
               }]
            }]
      }
      

      这将是一个接受产品列表的结构,并且在每个产品中都有项目列表(您已经拥有的)。

      在 Java 中:

      public class ProductList
      {
          List <ProductList> productList;
      }
      
      public class ProductList
      {
          String name;
          List<Product> items;
      } 
      

      使用您原来的 Product 类

      【讨论】:

      • 我的新对象中没有填充列表有什么问题:public class Inventory { public List&lt;Product&gt; getProducts() { return products; } public void setProducts(List&lt;Product&gt; products) { this.products = products; } private List&lt;Product&gt; products; }
      • 所以我做了“硬编码”解决方案,它确实填充了其中的所有列表和对象,所以这对我来说是一个巨大的进步。我确实需要一个包含任意数量的产品列表的解决方案,因为真正的结构太大而无法硬编码,这就是让我认为我必须深入研究 GSON 并弄清楚如何制作我自己的自定义反序列化器的原因。非常感谢您的帮助,我会给您一个赞成票,但我什至没有 15 个代表。
      • 我真的希望 API 能够提供不同的响应结构,但改变它是我无法控制的。我认为我无法说服任何人很快改变它。我感谢所有的帮助。
      【解决方案3】:

      我告诉 Retrofit (GSON?) 寻找 Map&lt;String,List&lt;Product&gt;&gt; 而不仅仅是 List&lt;Product&gt;,它发现了,多么方便。 :

              api.getInventory(new Callback<Map<String,List<Product>>>() {
                  @Override
                  public void success(Map<String,List<Product>> products, Response response) {
      
                      mInventory = products;
                  }
                  @Override
                  public void failure(RetrofitError error) {
                      Log.d(TAG,error.getMessage());
                  }
              });
      
      public interface ProductAPI {
          @GET("/v2/get-inventory")
          public void getInventory(Callback<Map<String,List<Product>>> response);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-06-11
        • 2015-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多