Десериализация произвольных объектных массивов json во внутренних классах с помощью Gson или вложенного внутреннего класса - PullRequest
1 голос
/ 17 декабря 2010

У меня проблемы, когда я пытаюсь десериализовать одну строку Json с помощью Gson. Строка идет примерно так (Примечание: я просто упростил это, но оставив ту часть, с которой у меня возникли проблемы, и из-за этого могут быть ошибки синтаксиса Json, но я проверил с помощью онлайн-валидатора, что строка, с которой я работаю, в порядке):

// 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 («определение» и «строки»). Остальные поля получают правильные значения при десериализации. Я использую следующее определение класса (для простоты нет методов получения / установки):

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

   public Container()
   {

   }
}

RateContainer (внутренний статический класс для класса Container, согласно спецификации Gson):

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 я использую:

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

и я получаю следующее исключение:

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

Похоже, в определении класса должно быть что-то, что не работает должным образом. Я проверил Gson API и знаю, что для десериализации списков обычно нужно сделать следующее:

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

поэтому я подумал, что, возможно, сначала смогу получить эти массивы, используя что-то вроде:

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

и затем получить «определение» и «строки», но я бы предпочел оставить все в объекте «Контейнер». Есть ли способ десериализации этих списков таким образом? Что-то не так в определении класса?

Спасибо всем заранее!

1 Ответ

6 голосов
/ 09 июня 2011

В ответ на несколько вещей в исходном вопросе обратите внимание на следующие три вещи:

  1. Gson не требует десериализации статических внутренних классов.
  2. Необходимо использовать толькообобщенный TypeToken, если тип для десериализации является обобщенной коллекцией.Если тип, подлежащий десериализации только в , содержит такой набор, то использование обобщенного TypeToken не является обязательным.
  3. Основное преимущество использования таких API, как Gson или Jackson, заключается впростое отображение и сериализация / десериализация структур данных Java в / из JSON.Таким образом, явного использования таких компонентов, как JsonElement, можно избежать.

С примером JSON, исправленным как

{
    "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"
            }
        ]
    }
}

... тогда следующая десериализация (и сериализация) простои, как и ожидалось.

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...