Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/180.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java GSON—如何解析两个同名但参数不同的JSONArray?_Java_Android_Json_Gson - Fatal编程技术网

Java GSON—如何解析两个同名但参数不同的JSONArray?

Java GSON—如何解析两个同名但参数不同的JSONArray?,java,android,json,gson,Java,Android,Json,Gson,在Reddit JSON API中,注释可以包含两种不同类型的JSONArray,都称为“children” “子对象”通常是包含字符串“种类”和对象“数据”的对象数组: 我一直处理得很好。我的问题是,有时,子对象将是一个简单的字符串数组: "children": [ "e78i3mq", "e78hees", "e78jq6q" ] 在分析这些时,GSON会引发如下异常: 原因:java.lang.IllegalStateException:应为BEGIN\u对象,但 was字符串位于第1行

在Reddit JSON API中,注释可以包含两种不同类型的JSONArray,都称为“children”

“子对象”通常是包含字符串“种类”和对象“数据”的对象数组:

我一直处理得很好。我的问题是,有时,子对象将是一个简单的字符串数组:

"children": [ "e78i3mq", "e78hees", "e78jq6q" ]
在分析这些时,GSON会引发如下异常:

原因:java.lang.IllegalStateException:应为BEGIN\u对象,但 was字符串位于第1行第3780列路径 $[1]。data.children[0]。data.replies.data.children[0]。data.replies.data.children[0]。data.replies.data.children[0]。data.children[0]


如何处理这些字符串数组情况?

如果同一端点在某些情况下返回不同的类型,我建议将该部分包装到对象中,并使用反序列化器检查类型并相应地分配。您可以这样做:

public Parent serialize(String jsonString) {
    GsonBuilder builder = new GsonBuilder();
    builder.registerTypeAdapter(WrappedChild.class, new ChildDeserializer());
    Gson gson = builder.create();
    return gson.fromJson(jsonString, Parent.class);
}

class Parent {
    public List<WrappedChild> children;
}

class ObjectChild {
    public String body;
}

class WrappedChild {
    public ObjectChild objectChild;
    public String stringChild;
}

class ChildDeserializer implements JsonDeserializer<WrappedChild> {
    private Gson gson = new Gson();

    @Override
    public WrappedChild deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        if (json != null) {
            if (json.isJsonObject()) {
                WrappedChild result = new WrappedChild();
                result.objectChild = gson.fromJson(json, ObjectChild.class);
                return result;
            } else if (json.isJsonPrimitive()) {
                WrappedChild result = new WrappedChild();
                result.stringChild = json.getAsString();
                return result;
            }
        }
        return null; // Or throw new Exception("Unknown child type");
    }
}
公共父序列化(字符串jsonString){
GsonBuilder=新的GsonBuilder();
registerTypeAdapter(WrappedChild.class,new ChildDeserializer());
Gson Gson=builder.create();
返回gson.fromJson(jsonString,Parent.class);
}
班级家长{
公开儿童名单;
}
类ObjectChild{
公共机构;
}
类包装儿童{
公众反对儿童反对儿童;
公共字符串和子字符串;
}
类ChildDeserializer实现JsonDeserializer{
private Gson Gson=new Gson();
@凌驾
public WrappedChild反序列化(JsonElement json,类型typeOfT,JsonDeserializationContext)引发JsonParseException{
if(json!=null){
if(json.isJsonObject()){
WrappedChild结果=新WrappedChild();
result.objectChild=gson.fromJson(json,objectChild.class);
返回结果;
}else if(json.isJsonPrimitive()){
WrappedChild结果=新WrappedChild();
result.stringChild=json.getAsString();
返回结果;
}
}
返回null;//或抛出新异常(“未知子类型”);
}
}

如果您正在使用改型,只需将生成器创建的Gson传递给
GsonConverterFactory。创建服务时将创建作为参数。

您应该仔细研究,因为这样您就可以完全控制反序列化。我将给出另一种方法,在某些情况下可能需要更少的努力。它基于
Gson
反序列化的“基本智能”

如果您声明包含子类的类,如:

public class Parent {
    Collection<?> children;
}
公共类父类{
收集儿童;
}
Gson
尽力“猜测”对象类型。如果它面对一个简单的字符串,它将被反序列化为
字符串
。如果它面对的数据与第一个
Json
示例类似,它将反序列化到
com.google.gson.internal.LinkedTreeMap
,这只是
Json
树的
Java
版本


因此,根据第一个示例中的
数据
对象的复杂程度以及整体使用结果的方式,您可能不需要编写自定义反序列化程序(这最终可能是更好的解决方案)。

很抱歉回答得太晚,感谢您将我引向正确的方向Emre

我最终让GsonBuilder使用一个自定义方法getGsonAdaptedData

在后台线程中检索JSON响应后:

...
Gson gson = new GsonBuilder().registerTypeAdapter(Data.class, (JsonDeserializer<Data>) (arg0, arg1, arg2) -> {
        JsonObject dataJsonObject = arg0.getAsJsonObject();
        Data data = new Gson().fromJson(dataJsonObject, Data.class);
        return RedditUtils.getGsonAdaptedData(dataJsonObject.get("children").getAsJsonArray(), data);
    }).create();
    final Feed responseSubredditFeed = gson.fromJson(jsonString, Feed.class);
...
。。。
Gson Gson=new GsonBuilder().registerTypeAdapter(Data.class,(JsonDeserializer)(arg0,arg1,arg2)->{
JsonObject dataJsonObject=arg0.getAsJsonObject();
Data Data=new Gson().fromJson(dataJsonObject,Data.class);
返回reddituitils.getGsonAdaptedData(dataJsonObject.get(“children”).getAsJsonArray(),data);
}).create();
最终提要响应subredditfeed=gson.fromJson(jsonString,Feed.class);
...
reddituitils.getGsonAdaptedData

// JSON returned for Reddit comments can contain two types of arrays named "children"
// This method checks to see if we were given a Children array or String array
// JSON member "replies" is similar, and can be found in the Data of some Children
// If the method finds a nested "children" array, it recursively adapts its Data
public static Data getGsonAdaptedData(JsonArray childrenJsonArray, Data data) {

    if (childrenJsonArray.size() > 0) {

        Gson gson = new Gson();

        if (childrenJsonArray.get(0).isJsonObject()) {

            data.setChildrenList(gson.fromJson(childrenJsonArray,
                    new TypeToken<List<Children>>() {
                    }.getType()));

            // Loops through every Data object in the array looking for children and replies
            for (int i = 0; i < childrenJsonArray.size(); i++) {

                JsonObject nestedDataJsonObject = childrenJsonArray.get(i).getAsJsonObject().get("data").getAsJsonObject();

                if (nestedDataJsonObject.has("children")) {
                    getGsonAdaptedData(nestedDataJsonObject.get("children").getAsJsonArray(), data.getChildren().get(i).getData());

                } else if (nestedDataJsonObject.has("replies") && nestedDataJsonObject.get("replies").isJsonObject()) {

                    data.getChildren().get(i).getData().setRepliesObject(gson.fromJson(nestedDataJsonObject.get("replies"),
                            new TypeToken<Replies>() {
                            }.getType()));

                    getGsonAdaptedData(nestedDataJsonObject.get("replies").getAsJsonObject().get("data").getAsJsonObject().get("children").getAsJsonArray(), data.getChildren().get(i).getData());
                }
            }
        } else {

            data.setRepliesList(gson.fromJson(childrenJsonArray,
                    new TypeToken<List<String>>() {
                    }.getType()));
        }
    }

    return data;
}
//为Reddit注释返回的JSON可以包含两种类型的名为“children”的数组
//此方法检查是否为我们提供了子数组或字符串数组
//JSON成员“回复”类似,可以在一些子级的数据中找到
//如果该方法找到嵌套的“子”数组,它将递归地调整其数据
公共静态数据GetgSonaAdaptedData(JsonArray儿童JsonArray,数据){
if(childrenJsonArray.size()>0){
Gson Gson=新的Gson();
if(childrenJsonArray.get(0.isJsonObject()){
data.setChildrenList(gson.fromJson(childrenJsonArray,
新的TypeToken(){
}.getType());
//循环遍历数组中的每个数据对象,查找子对象和回复
对于(int i=0;i
还有其他课程吗
// JSON returned for Reddit comments can contain two types of arrays named "children"
// This method checks to see if we were given a Children array or String array
// JSON member "replies" is similar, and can be found in the Data of some Children
// If the method finds a nested "children" array, it recursively adapts its Data
public static Data getGsonAdaptedData(JsonArray childrenJsonArray, Data data) {

    if (childrenJsonArray.size() > 0) {

        Gson gson = new Gson();

        if (childrenJsonArray.get(0).isJsonObject()) {

            data.setChildrenList(gson.fromJson(childrenJsonArray,
                    new TypeToken<List<Children>>() {
                    }.getType()));

            // Loops through every Data object in the array looking for children and replies
            for (int i = 0; i < childrenJsonArray.size(); i++) {

                JsonObject nestedDataJsonObject = childrenJsonArray.get(i).getAsJsonObject().get("data").getAsJsonObject();

                if (nestedDataJsonObject.has("children")) {
                    getGsonAdaptedData(nestedDataJsonObject.get("children").getAsJsonArray(), data.getChildren().get(i).getData());

                } else if (nestedDataJsonObject.has("replies") && nestedDataJsonObject.get("replies").isJsonObject()) {

                    data.getChildren().get(i).getData().setRepliesObject(gson.fromJson(nestedDataJsonObject.get("replies"),
                            new TypeToken<Replies>() {
                            }.getType()));

                    getGsonAdaptedData(nestedDataJsonObject.get("replies").getAsJsonObject().get("data").getAsJsonObject().get("children").getAsJsonArray(), data.getChildren().get(i).getData());
                }
            }
        } else {

            data.setRepliesList(gson.fromJson(childrenJsonArray,
                    new TypeToken<List<String>>() {
                    }.getType()));
        }
    }

    return data;
}