如何将不一致的JSON响应解析为两个子类中的任何一个?

时间:2017-02-18 21:07:10

标签: java android json rest gson

我正在使用Retrofit2和Gson来检索和解析从一个安静的Web服务到一个Android客户端的JSON字符串。

我有类似于以下模拟类的东西:

public class User {
    String name;
    String email;
    String gender;
    String phone;
    String type;

    //getters and setters.
}

2个子类(未来可能更多):

ShopOwner:

public class ShopOwner extends User {
    String shopName;
    String shopDescription;
    Country shopCountry;

    //getters and setters.
}

买方:

public class Buyer extends User {
    float availableCredit;
    long lastPurchase;

    /getters and setters.
}
  • 为简洁起见,省略了序列化注释。

当我触发登录请求并成功登录时,我会收到以下JSON响应之一:

此:

{
    "name": "John Doe",
    "email": "john@doe.com",
    "gender": "male",
    "phone": "1234567890",
    "type": "shop owner",
    "shop_owner": {
        "shop_name": "Flower Market",
        "shop_description": "Fresh Flowers Everyday",
        "shop_country": {
            "name": "United Stated of America",
            "short_name": "US"
        }
    }
}

或者这个:

{
    "name": "John Doe",
    "email": "john@doe.com",
    "gender": "male",
    "phone": "1234567890",
    "type": "buyer",
    "buyer": {
        "available_credit": 200,
        "last_purchase": 1527915600
    }
}

所以我的问题是:

1)我收到的回复结构是否被认为是最佳实践"?或者后端的人应该重组响应,将超类和子类中的键组合成一个对象?这样我就可以简单地检查type属性,并相应地将对象解析为2个子类中的任何一个。

2)如果我收到的回复实际上是根据最佳实践构建的,我该如何有效地解析它? TypeAdapter似乎是一个荒谬的答案,因为,严重的是,我必须将所有值存储在等待来自流的类型键的变量中,这听起来不太好听!另一种方法是在User类中创建子类组合,我真的不喜欢这个解决方案,因为一个或另一个将始终为null,我相信继承是为了在这些情况下使用而创建的。

非常感谢您的帮助!

修改

换句话说,我认为必须使用TypeAdapter来处理这样的结构化JSON字符串是荒谬的,因为我认为JSON应该以适合继承概念的另一种方式构建。下面是我的示例中提供的简单模拟类的TypeAdapter读取方法的示例:

public User read(JsonReader reader) throws IOException {
    if (reader.peek() == JsonToken.NULL) {
        reader.nextNull();
        return null;
    }
    boolean isShopOwner = true;
    User user = new User();
    HashMap<String, String> values = new HashMap<>();
    Country country = new Country();
    reader.beginObject();
    while (reader.hasNext()) {
        String key = reader.nextName();
        switch (key) {
            case "shop_owner":
            case "buyer":
                if (key.equals("buyer"))
                    isShopOwner = false;
                reader.beginObject();
                while (reader.hasNext()) {
                    String key2 = reader.nextName();
                    if (key2.equals("country")) {
                        reader.beginObject();
                        while (reader.hasNext()) {
                            switch (reader.nextName()) {
                                case "name":
                                    country.setName(reader.nextString());
                                    break;
                                case "short_name":
                                    country.setShortName(reader.nextString());
                                    break;
                            }
                        }
                        reader.endObject();
                    }
                    else
                        values.put(key2, reader.nextString());
                }
                reader.endObject();
                break;
            default:
                values.put(key, reader.nextString());
        }
    }
    user.setName(values.get("name"));
    user.setEmail(values.get("email"));
    user.setGender(values.get("gender"));
    user.setPhone(values.get("phone"));
    user.setType(values.get("type"));
    if (isShopOwner) {
        ShopOwner shopOwner = user;
        shopOwner.setShopName(values.get("shop_name"));
        shopOwner.setShopDescription(values.get("shop_description"));
        shopOwner.setCountry(country);
        return shopOwner;
    }
    else {
        Buyer buyer = user;
        buyer.setAvailableCredit(values.get("available_credit"));
        buyer.setLastPurchase(values.get("last_purchase"));
        return buyer;
    }
}

我的实际类更复杂,并且它们嵌入了许多对象,除了我必须检查我从read方法返回的实例这一事实,因为我真的不知道它是否会返回ShopOwner或Buyer对象。我相信必须有一个更清洁的方法!

0 个答案:

没有答案