Android-Retrofit Gson-如何在JSON响应中解析JSON字符串以指向JSON键的对象?

MA1*_*A13 5 android json gson retrofit2

这是我的JSON响应:

{
      "id": 2,
      "name": "Test",
      "content": "{\"type\": \"status\", \"text\": \"Lorem ipsum dummy text.\", \"id\": 1}"
}
Run Code Online (Sandbox Code Playgroud)

这些是模型结构:

class TestModel {
    public int id;
    public String name;
    public Content content;
}

class Content {
    public int id;
    public String status;
    public String text;
}
Run Code Online (Sandbox Code Playgroud)

我想使用Retrofit和GsonConvertor将内容的值直接解析到我的Content模型对象中。但是目前,我将其解析为String值,而不是使用Gson.fromJson()转换为我的Content模型对象。有什么解决方案可以达到我的预期结果吗?

当我过去使用GsonConverterFactory解析它时,Retrofit在onFailure方法中提供了回调,但有以下例外:

java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 4 column 19 path $.data[0].content
Run Code Online (Sandbox Code Playgroud)

Bry*_*yan 3

问题在于 JSON 响应,它的JSON 格式不正确。该"content"字段应该是一个对象,而不是字符串:

{
    "id": 2,
    "name": "Test",
    "content": {
        "type": "status",
        "text": "Lorem ipsum dummy text.",
        "id": 1
    }
}
Run Code Online (Sandbox Code Playgroud)

这将允许gson.fromJson(response, TestModel.class)RetroFit与 aGsonConverterFactory将您的响应正确解析为相应的对象。


当然,这只适用于您能够更改收到的 JSON 响应的情况。如果不是,首先确保控制响应的人知道他们做错。如果没有任何变化,那么您应该可以通过将contentin更改TestModel为 a来解决此问题String

class TestModel {
    public int id;
    public String name;
    public String content;
}

class Content {
    public int id;
    public String type;
    public String text;
}
Run Code Online (Sandbox Code Playgroud)

然后分别解析每个对象:

TestModel testModel = gson.fromJson(response, TestModel.class);
Content content = gson.fromJson(testModel.content, Content.class);
Run Code Online (Sandbox Code Playgroud)

TypeAdapter如果无法更改响应,另一种选择是为您的Content对象创建一个:

public class ContentAdapter extends TypeAdapter<Content> {

    @Override
    public void write(JsonWriter out, Content value) throws IOException {
        // TODO: Writer implementation
    }

    @Override
    public Content read(JsonReader in) throws IOException {
        if(in.peek() != JsonToken.NULL) {
            return fromJson(in.nextString());
        } else {
            in.nextNull();
            return null;
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

然后将其添加TypeAdapter到您的 GSON 实现中:

Gson gson = new GsonBuilder()
        .registerTypeAdapter(Content.class, new ContentAdapter()).create();
Run Code Online (Sandbox Code Playgroud)