1

1 つの 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 (Gson 仕様によると、クラス Container への内部静的クラス):

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");

次に、「定義」と「行」を取得しますが、すべてを Container オブジェクトに保持することをお勧めします。このような方法でこれらのリストを逆シリアル化する方法はありますか? クラス定義に何か問題がありますか?

よろしくお願いします!

4

1 に答える 1

6

元の質問のいくつかの点に対応して、次の 3 つの点に注意してください。

  1. Gson は静的内部クラスへの逆シリアル化を必要としません。
  2. TypeToken逆シリアル化される型がジェネリック コレクションである場合にのみ、ジェネリックを使用する必要があります。逆シリアル化される型にそのようなコレクションのみが含まTypeTokenれる場合、ジェネリックを使用する必要はありません。
  3. Gson や Jackson などの API を使用する主な利点は、JSON との間で Java データ構造を単純にマッピングし、シリアル化/逆シリアル化できることです。したがって、コンポーネントの明示的な使用は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;
}
于 2011-06-09T16:57:28.443 に答える