【问题标题】:Parse JSON using Gson (or alternative for java)使用 Gson(或 java 的替代方法)解析 JSON
【发布时间】:2015-04-24 18:13:55
【问题描述】:

我已经与 Gson 合作了很长一段时间,但这一次让我摸不着头脑。这是我从 REST 调用中得到的典型 json 响应。请注意,有几个相同类型的嵌套引用。知道如何使用 Gson(或其他 java 库)解决这个问题,而无需进行字符串操作吗?

我尝试使用注释来声明相同的名称,但最终得到:

@SerializedName("上下文")

声明多个名为 Context 的 JSON 字段

"response": {
    "Context": {
        "Context": {
            "ttContext": [
                {
                    "taskId": "",
                    "name": "GUID",
                    "value": "abc123"
                }
            ]
        }
    },
    "Data": {
        "Data": {
            "ttData": [
                {
                    "name": "Bob Brown",
                    "address": "101 Anywhere St",
                    "city": "Spruce Pine",
                    "state": "AL",
                    "zipcd" : 12345
                }
            ]
        }
    }
}

【问题讨论】:

  • 它们不是同一类型。

标签: java json rest gson


【解决方案1】:

我在下面所做的是创建一个可以通过构造函数包含自身的 Java 类。

我实际上创建了一个 JUnit 测试。我还放了所有的 getter/setter,所以对于这个论坛来说它可能不必要地太长了。我很抱歉。

import com.google.gson.Gson;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

public class TestThrowaway {

public class Container {
    Response response;

    public Container() {
    }

    public Response getResponse() {
        return response;
    }

    public void setResponse(Response response) {
        this.response = response;
    }
}

public class Response {
    private Context Context;
    private Data Data;

    public Response() {
    }

    public TestThrowaway.Context getContext() {
        return Context;
    }

    public void setContext(TestThrowaway.Context context) {
        Context = context;
    }

    public TestThrowaway.Data getData() {
        return Data;
    }

    public void setData(TestThrowaway.Data data) {
        Data = data;
    }
}

public class Context {
    private Context Context;
    private List<TtContext> ttContext;

    public Context() {}
    public Context(Context context) {
        this.Context = context;
    }

    public TestThrowaway.Context getContext() {
        return Context;
    }

    public void setContext(TestThrowaway.Context context) {
        Context = context;
    }

    public List<TtContext> getTtContext() {
        return ttContext;
    }

    public void setTtContext(List<TtContext> ttContext) {
        this.ttContext = ttContext;
    }
}

public class TtContext {
    private String taskId;
    private String name;
    private String value;

    public TtContext(String taskId, String name, String value) {
        this.taskId = taskId;
        this.name = name;
        this.value = value;
    }

    public TtContext() {
    }

    public String getTaskId() {
        return taskId;
    }

    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

public class Data {
    private Data Data;
    private List<TtData> ttData;

    public Data() {
    }

    public Data(TestThrowaway.Data data) {
        Data = data;
    }

    public TestThrowaway.Data getData() {
        return Data;
    }

    public void setData(TestThrowaway.Data data) {
        Data = data;
    }

    public void setTtData(List<TtData> ttData) {
        this.ttData = ttData;
    }

}

public class TtData {
    private String name;
    private String address;
    private String city;
    private String state;
    private Integer zipcd;

    public TtData() {
    }

    public TtData(String name, String address, String city, String state, Integer zipcd) {
        this.name = name;
        this.address = address;
        this.city = city;
        this.state = state;
        this.zipcd = zipcd;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public Integer getZipcd() {
        return zipcd;
    }

    public void setZipcd(Integer zipcd) {
        this.zipcd = zipcd;
    }
}

@Test
public void test() {
    // Create inner Context object
    Context innerContext = new Context();

    // Create your ttContext list. For ease, I created a constructor that takes in all of your values
    List<TtContext> ttContexts = new ArrayList<>();
    ttContexts.add(new TtContext("", "GUID", "abc123"));

    // Add your list to your inner Context
    innerContext.setTtContext(ttContexts);

    // Create a new Context object that takes in a Context object, the inner Context object
    Context outsideContext = new Context(innerContext);

    // Create inner Data object
    Data innerData = new Data();

    // Create your ttData list.
    List<TtData> ttDatas = new ArrayList<>();
    ttDatas.add(new TtData("Bob Brown", "101 Anywhere St", "Spruce Pine", "AL", 12345));

    // Add your list to your inner Data
    innerData.setTtData(ttDatas);

    // Create a new Data object that takes in a Data object, the inner Data object
    Data outsideData = new Data(innerData);

    // Create a Response object that will set both the outsideContext object and the outsideData object
    Response response = new Response();
    response.setContext(outsideContext);
    response.setData(outsideData);

    // If you leave like this and run Gson, you won't have the wrapping "response" object.  
    // I like to create a Container object that takes in the Response object so I can create a variable 
    // called response and Gson does everything for me.  

    Container container = new Container();
    container.setResponse(response);

    // Instantiate Gson and run the method toJson.
    Gson gson = new Gson();
    String s = gson.toJson(container);
    System.out.println(s);
}
}

测试结果是:

{
  "response": {
    "Context": {
      "Context": {
        "ttContext": [
          {
            "taskId": "",
            "name": "GUID",
            "value": "abc123"
          }
        ]
      }
    },
    "Data": {
      "Data": {
        "ttData": [
          {
            "name": "Bob Brown",
            "address": "101 Anywhere St",
            "city": "Spruce Pine",
            "state": "AL",
            "zipcd": 12345
          }
        ]
      }
    }
  }
}

【讨论】:

  • 哇!这和 elbuild 都是很好的答案,但由于细节原因,必须将其标记为已接受。
  • 旁注.. 如果您曾经打算在 Resteasy 项目中使用 JAX-RS,则此解决方案可能无法完全按照您想要的方式工作。这就是为什么我在我的 Resteasy 项目中创建了一个 GsonProvider,它基本上处理我的 JSON 对象的序列化/反序列化。 Gson 是我发现的唯一一个既易于使用又可以双向工作(序列化/反序列化)的工具。 JAX-RS 内部类存在一些(或有)问题。
【解决方案2】:

如果您将它们视为 JSON 结构,它们就不是同一类型。它们可以用一堆(几乎是无意义的)类来表示,如下所示。

public class Response()
{
    public Response(){}

    private ExternalContext Context;
    private ExternalData Data;
}

public class ExternalContext
{
    public ExternalContext(){}

    private IntermediateContext Context;

}

public class IntermediateContext
{
    public IntermediateContext(){}

    private Context ttContext;
}

public class Context
{
    public Context(){}

    private String taskId;
    private String name;
    private String value;
}

// the same idea can be applied to ExternalData

您只需要使用 GSON 来反序列化 Response。

【讨论】:

  • 如果你重用相同的 Context 类,它可以被简化。这样,您可以嵌套任意数量的 Context 对象,而不必每次都定义新对象。请参阅下面的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-28
  • 2011-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-17
相关资源
最近更新 更多