【问题标题】:Moshi and Retrofit2 : Expected BEGIN_OBJECT but was STRINGMoshi 和 Retrofit2:应为 BEGIN_OBJECT 但为 STRING
【发布时间】:2020-05-19 01:57:14
【问题描述】:

我在我的项目中遇到了这个问题。我从 api 调用收到如下响应:

{
    "aResponse": {
        "listOfSomething": [
             //here some data
        ]
    }
}

而相对数据类是

data class ResponseClass(
    val aResponse : AResponse
) 

data class AResponse(
    val listOfSomething : List<String>
)

当“listOfSomething”为空时,我不会收到此响应:

{
    "aResponse": {
        "listOfSomething": ""
    }
}

抛出(当然)异常

com.squareup.moshi.JsonDataException: Expected BEGIN_OBJECT but was STRING

我该如何解决?

【问题讨论】:

  • 在第一步中,我从nulls 和[] 中清除JSON,参见stackoverflow.com/a/54709501/2914140。在第二步中,我解析该 JSON。
  • 糟糕的后端先生。
  • 后端不在我的控制之下:)

标签: android json kotlin retrofit2 moshi


【解决方案1】:

如果你的 json 结果会根据结果而改变,首先你的后端做得不好,那么你必须“破解”你的应用程序以适应代码......

你的 POJO 类应该是:

data class MyResponse(
    val aResponse: AResponse
)

data class AResponse(
    val listOfSomething: Any
)

您可以将其声明为Any,这不是一个好习惯,但它是一种解决方法,可以使其根据您的后端工作。就像在Java中添加Object

然后你可以在你的onResponse做一些事情

@Override
fun onResponse(response: Response<MyResponse>) {
    if (response.isSuccess()) {
        if (response.listOfSomething is String) {
            //do something with the String
        } else {
            //do something with the List
        }
    }
}

【讨论】:

  • @giozh 你解决了吗?为了帮助其他人,如果这有助于您随时投票并将其标记为正确答案。谢谢:)
【解决方案2】:

首先,您的后端实现是错误的。 您不应该发送一个空字符串来表示一个空数组。

如果由于 API 不受您的控制而无法在后端修复它,您可以尝试以下方法:

public final class IgnoreStringForArrays implements JsonAdapter.Factory {

    @Retention(RetentionPolicy.RUNTIME)
    @JsonQualifier
    public @interface IgnoreJsonArrayError {
    }

    @Override
    public JsonAdapter<?> create(Type type, Set<? extends Annotation> annotations, Moshi moshi) {
        if (annotations != null && annotations.size() > 0) {
            for (Annotation annotation : annotations) {
                if (annotation instanceof IgnoreJsonArrayError) {
                    final JsonAdapter<Object> delegate = moshi.nextAdapter(this, type, Types.nextAnnotations(annotations, IgnoreJsonArrayError.class));
                    return new JsonAdapter<Object>() {
                        @Override
                        public Object fromJson(JsonReader reader) throws IOException {
                            JsonReader.Token peek = reader.peek();
                            if (peek != JsonReader.Token.BEGIN_ARRAY) {
                                reader.skipValue();
                                return null;
                            }
                            return delegate.fromJson(reader);
                        }

                        @Override
                        public void toJson(JsonWriter writer, Object value) throws IOException {
                            delegate.toJson(writer, value);
                        }
                    };
                }
            }
        }
        return null;
    }
}

喜欢这里的建议:https://github.com/square/moshi/issues/295#issuecomment-299636385

然后用 IgnoreJsonArrayError 注释你的 listOfSomething 注释

【讨论】:

    【解决方案3】:

    当你得到数组的数据和没有数据得到字符串时,你会得到这个错误,这在改造中是错误的。

    如果 listOfSomething 中没有数据,则要求后端发送空数组而不是字符串。

    {
        "aResponse": {
            "listOfSomething": []
        }
    }
    

    而不是

    {
        "aResponse": {
            "listOfSomething": ""
        }
    }
    

    【讨论】:

    • 没错,为什么后端甚至会返回一个与预期列表相反的字符串
    • 许多后端都是哑火。我亲身经历过公司雇用的学生大部分时间都不知道自己在做什么的情况。它们是便宜的替代品:D
    • 我的问题与此类似。数组作为字符串返回,并且还有正斜杠。如果 moshi 已经为此建立了一个内置工厂,那就太好了
    猜你喜欢
    • 1970-01-01
    • 2018-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-29
    • 2015-11-06
    • 2016-06-01
    • 2023-04-07
    相关资源
    最近更新 更多