使用 Gson 或嵌套内部类反序列化内部类中的任意对象 json 数组 [英] Deserializing arbitrary object json arrays in inner classes with Gson or nested inner class

查看:57
本文介绍了使用 Gson 或嵌套内部类反序列化内部类中的任意对象 json 数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我尝试使用 Gson 反序列化一个 Json 字符串时遇到了麻烦.字符串是这样的(注意:我只是简化了它,但留下了我遇到问题的部分,因此,可能存在 Json 语法错误,但我已使用在线验证器检查我正在使用的字符串是否正常):

I am having troubles when I try to deserialize one Json string with Gson. The string goes something like this (Note: I just simplified it, but leaving the part I am having troubles with and because of that, there might be Json syntaxis errors, but I have checked with an online validator that the string I am working with is OK):

// let's call this "container" json element
{
"context": "context", 
"cpuUsage": cpuUsageValue,  
"name": "thename",
"rates": {
    "definition": [
        {
        "key": "name",
        "type": "string"
        },
        {
        "key": "rate",
        "type": "double"
        }       
    ]
    "rows": [
        {
        "name": "thename1",
        "rate": therate
        },
        {
        "name": "thename2",
        "rate": therate2
        }
    ]
}

现在,我遇到的问题是当我尝试反序列化 json 数组(定义"和行")时.其余字段在反序列化中获得正确的值.我使用的类定义如下(为了简单起见,没有 getter/setter):

Now, the problem I get is when I try to deserialize the json arrays ("definition" and "rows"). Rest of fields get proper values in deserialization. The class definition I am using is the following (no getters/setters for simplicity):

public class Container
{
   private String context;
   private Double cpuUsage;
   private String name;   
   private RateContainer rates;

   public Container()
   {

   }
}

RateContainer(内部静态类到类 Container,根据 Gson 规范):

RateContainer (inner static class to class Container, according to Gson specs):

public static class RateContainer
{
    private List<DefinitionContainer> definition;
    private List<RowsContainer> rows;

    public static class DefinitionContainer
    {
        String key;
        String type;

        public DefinitionContainer()
        {
        }
    }

    public static class RowsContainer
    {
        String name;
        Double rate; 

        public RowsContainer()
        {
        }
    }

    public RateContainer()
    {
    }
}

要解析 Json 字符串,我使用:

To parse the Json string, I use:

Container container = gson.fromJson(containerString, Container.class);

我得到以下异常:

Expecting object found: [{"key":"name","type":"string"},{"key":"rate","type":"double"}]

看起来类定义中必须有一些不能正常工作的东西.我检查了 Gson API,我知道为了反序列化列表,通常要做的事情是:

Looks like there has to be something in the class definition that does not work well. I have checked the Gson API and I know that, in order to deserialize lists, the usual thing to do is:

Type collectionType = new TypeToken<Collection<Integer>>(){}.getType();
Collection<Integer> ints2 = gson.fromJson(json, collectionType);

所以我想也许我可以先得到这些数组,使用类似的东西:

so I thought that maybe I could get these arrays first, using something like:

JsonElement element = containerJsonElement.getAsJsonObject().get("rates");

然后获取定义"和行",但我更愿意将所有内容都保留在 Container 对象中.有没有办法以这种方式反序列化这些列表?类定义有问题吗?

and then get "definition" and "rows", but I would prefer to keep everything in the Container object. Is there a way to deserialize these lists in such a way? Is there something wrong in the class definition?

先谢谢大家!

推荐答案

针对原问题中的几个问题,注意以下三点:

In response to a few things in the original question, note the following three things:

  1. Gson 不需要反序列化为静态内部类.
  2. 如果要反序列化的类型是泛型集合,则仅需要使用泛型 TypeToken.如果要反序列化为仅包含这样的集合的类型,则不需要使用泛化的TypeToken.
  3. 使用 Gson 或 Jackson 等 API 的一个主要好处是可以将 Java 数据结构简单地映射和序列化/反序列化到/从 JSON.因此,可以避免显式使用 JsonElement 等组件.
  1. Gson does not require deserialization to static inner classes.
  2. It's only necessary to use a generified TypeToken if the type to be deserialized to is a generified collection. If the type to be deserialized to only contains such a collection, then use of a generified TypeToken is not necessary.
  3. A major benefit of using an API like Gson or Jackson is for simple mapping and serialization/deserialization of Java data structures to/from JSON. So, explicite use of components like JsonElement can be avoided.

将示例 JSON 更正为

With the example JSON corrected as

{
    "context": "context", 
    "cpuUsage": "cpuUsageValue",  
    "name": "thename",
    "rates": {
        "definition": [
            {
                "key": "name",
                "type": "string"
            },
            {
                "key": "rate",
                "type": "double"
            }       
        ],
        "rows": [
            {
                "name": "thename1",
                "rate": "therate"
            },
            {
                "name": "thename2",
                "rate": "therate2"
            }
        ]
    }
}

...然后以下内容按预期简单地反序列化(和序列化).

...then the following deserializes (and serializes) simply and as expected.

import java.io.FileReader;
import java.util.List;

import com.google.gson.Gson;

public class Foo
{
  public static void main(String[] args) throws Exception
  {
    Gson gson = new Gson();
    Container container = gson.fromJson(new FileReader("input.json"), Container.class);
    System.out.println(gson.toJson(container));
  }
}

class Container
{
  private String context;
  private String cpuUsage;
  private String name;
  private Rates rates;
}

class Rates
{
  private List<Definition> definition;
  private List<Row> rows;
}

class Definition
{
  private String key;
  private String type;
}

class Row
{
  private String name;
  private String rate;
}

这篇关于使用 Gson 或嵌套内部类反序列化内部类中的任意对象 json 数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆