【问题标题】:How to write a Pojo using a dynamic key inside JSONarray如何使用 JSONarray 中的动态键编写 Pojo
【发布时间】:2019-06-09 03:09:44
【问题描述】:

我什至不知道这是否是一个有效的问题,但我很难将 API 结果转换为 POJO,因为某些键是动态的。

{
"data": [{
        "something_edit": true
    },
    {
        "test_null": false
    }
],
"success": true

}

如您所见,内部数据的关键是动态的。我尝试使用 jsonschema2pojo 或其他转换器,但它声明了一个命名变量,这不是一个好的结果。顺便说一句,我正在使用改造和 GSON 库

编辑:

这就是流程,所以密钥是我在 API 上询问的。因此,对于示例,我询问了 something_edit1、something_edit2 和 something_edit3。数据结果将是。

{

"data": [{
        "something_edit1": true
    }, {
        "something_edit2": false
    },
    {
        "something_edit3": false
    }
],

"success": true
}

【问题讨论】:

  • 我从你的问题中了解到的。数据中的键是动态的,就像您有时会得到键“something_edit”,有时会得到键“test_null”,有时会同时得到键。我的问题是得到的钥匙得到确认,就像这样确认钥匙的名称将是相同的,并且会得到一些钥匙??
  • 您的数据变量是预定义的还是随时会被声明为新的?就像我为一个应用程序编写代码一样,其中我得到了不同对象的数组列表......所以我通过检测类型来解析它们......所以如果你有这种情况,那么我可以帮助你......
  • @sourabhkaushik 是的,对于您的问题,有时数据的值可能会根据我的要求而改变。例如我请求something_edit1,something_edit2,something_edit3 那么数据结果应该是“data”:[{“something_edit1”:true},{“something_edit2”:false},{“something_edit3”:false}]
  • @Hanzala 请参阅编辑

标签: android retrofit pojo


【解决方案1】:

您可以根据自己的情况使用Json ObjectGenerics

使用 Json 对象,您可以检查您的 json 中是否存在密钥。

if(yourJsonObject.hasOwnProperty('key_name')){
   // do your work here
}

使用 Generic 你必须检查你的 Pojo 是否有 波乔。

if(YourMainPOJO instanceOf YourChildPojo){
   // do your work here
}

尝试仅查看此link 中的通用部分。

【讨论】:

  • 嗨,实际上我正在使用改造,它会返回包含数据的 Pojo 类,这就是为什么我需要 pojo 来处理它。我明白你的意思,更容易获得响应字符串并根据我的要求对其进行修改。谢谢
  • @Androyds 改造也返回 json。如果您需要帮助,请告诉我。我认为使用 Objects 处理这种动态 POJO 可能很困难。
【解决方案2】:

很难确定,或者您必须在 POJO 中声明所有可能的字段,或者编写自己的 json 解析器来扩展 Gson 解析器,或者使用可以转换为 json 数组、对象和原语的 JsonElement,根据您的结果可以转换回某些特定的 pojo。

   /**
 * this will convert the whole json into map which you can use to determine the json elements
 *
 * @param json
 */
private void getModelFromJson(JsonObject json) {
    Gson gson = new Gson();
    Map<String, JsonElement> jsonElementMap = gson.fromJson(json.toString(), new TypeToken<Map<String, JsonElement>>() {
    }.getType());
    for (Map.Entry<String, JsonElement> jsonElementEntry : jsonElementMap.entrySet()) {
        if (jsonElementEntry.getValue().isJsonPrimitive()) {
            //json primitives are data types, do something
            //get json boolean
            //you can here also check if json element has some json object or json array or primitives based on that
            //you can convert this to something else after comparison
            if (true) {
                InterestModelResponse response = gson.fromJson(jsonElementEntry.getValue().getAsJsonObject().toString(), InterestModelResponse.class);
                //use your dynamic converted model
            }
        } else {
            //do something else
        }
    }

}

【讨论】:

  • 我想现在它要么使用响应字符串,根据响应创建 pojo,要么在 POJO 上添加所有键。感谢您的澄清。
【解决方案3】:

2 年前,我们做了一个项目,在该项目中,我们必须在使用改造时处理的同一数组中处理具有不同类型对象的通知数据

这是我们的改造Creator

class Creator {
    public static FullTeamService newFullTeamService() {
        final HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        final OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .build();

        final Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(FullTeamService.HOST)
                .client(client)
                .addConverterFactory(GsonConverterFactory.create(GsonUtils.get()))
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        return retrofit.create(FullTeamService.class);
    }
}

GsonUtils.java 是:

public class GsonUtils {
    private static final Gson sGson = new GsonBuilder()
        .setDateFormat("yyyy-MM-dd'T'HH:mm:ss")
        .registerTypeAdapter(NotificationObject.class, new NotificationDeserializer())
        .create();

   private GsonUtils() {}

   public static Gson get() {
    return sGson;
   }
}

NotificationObject 类似于:

public class NotificationObject {

@SerializedName("ID")
@Expose
private long ID;

@SerializedName("type")
@Expose
private Type type;

@SerializedName("DataObject")
@Expose
private NotificationDataObject dataObject;

public void setDataObject(NotificationDataObject newsFields) {
    dataObject = newsFields;
}

@SuppressWarnings("unchecked")
public <T> T getDataObject() {
    return (T) dataObject;
}
public enum Type {
    @SerializedName("0")
    CHAT_MESSAGE,
    @SerializedName("10")
    GAME_APPLICATION,
    @SerializedName("20")
    GAME_APPLICATION_RESPONSE,
    @SerializedName("30")
    GAME_INVITE....
}
}

NotificationDataObject 作为新类是这样的:

public class NotificationDataObject {}

最后NotificationDeserializer 就像:

public class NotificationDeserializer implements JsonDeserializer<NotificationObject> {
@Override
public NotificationObject deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
    final JsonObject itemBean = json.getAsJsonObject();
    final NotificationObject object = GsonUtils.getSimpleGson().fromJson(itemBean, NotificationObject.class);
    switch (object.getType()) {
        case CHAT_MESSAGE:
            break;
        case GAME_APPLICATION:
            object.setDataObject(GsonUtils.get().fromJson(itemBean.get("DataObject").getAsJsonObject(),
                    GameApplicationNotification.class));
            break;
        case GAME_APPLICATION_RESPONSE:
            object.setDataObject(GsonUtils.get().fromJson(itemBean.get("DataObject").getAsJsonObject(),
                    GameApplicationResponseNotification.class));
            break;
        case GAME_INVITE:
            object.setDataObject(GsonUtils.get().fromJson(itemBean.get("DataObject").getAsJsonObject(),
                    GameInviteNotification.class));
            break;
}
    return object;
}
}

编码愉快...!

任何查询将不胜感激...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-17
    • 1970-01-01
    • 2018-12-08
    • 1970-01-01
    • 1970-01-01
    • 2017-12-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多