使用GSON解析多类型数组

gstyhher  于 2022-11-06  发布在  其他
关注(0)|答案(2)|浏览(184)

我希望使用GSON来解析下面的json:

[
    [
        "hello",
        1,
        [2]
    ],
    [
        "world",
        3,
        [2]
    ]
]

这是一个数组,包含两个数组,两个内部数组本身就是数组,由String,int,数组类型组成.
我不确定如何使用Java类来对具有3种不同类型(String、int、array)的数组进行建模。我从以下内容开始:

// String json just contains the aforementioned json string.

ArrayList<ArrayList<XXX>> data = new ArrayList<ArrayList<XXX>>();

Type arrayListType = new TypeToken<ArrayList<ArrayList<XXX>>>(){}.getType();

data = gson.fromJson(json, arrayListType);

但是,“XXX”应该在什么位置呢?我认为它应该是一个数组,但是它应该是一个具有3种不同数据类型的数组。那么,我该如何使用Java来建模呢?
需要帮忙吗?谢谢。

xu3bshqb

xu3bshqb1#

Gson有一个特殊的处理方法,可以将一些单元素数组反序列化为非数组类型。例如,int data = gson.fromJson("[3]", int.class);会将int值3赋给data。
当然,将单组件数组反序列化为非数组类型并不是必需的。例如,前面的示例可以反序列化为int[] data = gson.fromJson("[3]", int[].class);
Gson也经常在被要求时将非String值反序列化为String。将这一点应用到第一个示例中,String data = gson.fromJson("[3]", String.class);也同样有效。
请注意,告诉Gson将第一个示例反序列化为Object类型是不起作用的。Object data = gson.fromJson("[3]", Object.class);会导致一个解析异常,抱怨[3]不是原语。
应用到上面原始问题中的示例,如果可以将所有值都视为String,那么反序列化就变得简单了。

// output:
// hello 1 2 
// world 3 2 

public class Foo
{
  static String jsonInput = 
    "[" +
      "[\"hello\",1,[2]]," +
      "[\"world\",3,[2]]" +
    "]";

  public static void main(String[] args)
  {
    Gson gson = new Gson();
    String[][] data = gson.fromJson(jsonInput, String[][].class);
    for (String[] data2 : data)
    {
      for (String data3 : data2)
      {
        System.out.print(data3);
        System.out.print(" ");
      }
      System.out.println();
    }
  }
}

不幸的是,使用Gson时,我无法找到一种简单的反序列化方法,该方法允许“更好地”绑定到数组中更特定的混合类型,因为Java没有提供定义混合类型数组的语法。例如,在最初的问题中,集合的首选类型可能是List<List<String, int, List<int>>>,但这在Java中是不可能定义的。因此,您必须满足于List<List<String>> (or String[][]),或者转向使用更多“手动”解析方法。
(Yes,Java允许List<List<Object>>的型别宣告,但Object不是足够特定的型别,无法有意义地还原序列化为。此外,如前所述,尝试将[3]还原序列化为Object会导致剖析例外状况。)
小更新:我最近不得不反序列化一些松散的JSON,其中包含的结构与原始问题中的结构没有太大的不同。我最终只是使用了一个自定义反序列化器从混乱的JSON数组中创建了一个对象。类似于以下示例。

// output: 
// [{MyThreeThings: first=hello, second=1, third=[2]}, 
//  {MyThreeThings: first=world, second=3, third=[4, 5]}]

import java.lang.reflect.Type;
import java.util.Arrays;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;

public class FooToo
{
  static String jsonInput =
      "[" +
          "[\"hello\",1,[2]]," +
          "[\"world\",3,[4,5]]" +
      "]";

  public static void main(String[] args)
  {
    GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.registerTypeAdapter(MyThreeThings.class, new MyThreeThingsDeserializer());
    Gson gson = gsonBuilder.create();
    MyThreeThings[] things = gson.fromJson(jsonInput, MyThreeThings[].class);
    System.out.println(Arrays.toString(things));
  }
}

class MyThreeThings
{
  String first;
  int second;
  int[] third;

  MyThreeThings(String first, int second, int[] third)
  {
    this.first = first;
    this.second = second;
    this.third = third;
  }

  @Override
  public String toString()
  {
    return String.format(
        "{MyThreeThings: first=%s, second=%d, third=%s}",
        first, second, Arrays.toString(third));
  }
}

class MyThreeThingsDeserializer implements JsonDeserializer<MyThreeThings>
{
  @Override
  public MyThreeThings deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
      throws JsonParseException
  {
    JsonArray jsonArray = json.getAsJsonArray();
    String first = jsonArray.get(0).getAsString();
    int second = jsonArray.get(1).getAsInt();
    JsonArray jsonArray2 = jsonArray.get(2).getAsJsonArray();
    int length = jsonArray2.size();
    int[] third = new int[length];
    for (int i = 0; i < length; i++)
    {
      int n = jsonArray2.get(i).getAsInt();
      third[i] = n;
    }
    return new MyThreeThings(first, second, third);
  }
}

Gson用户指南确实介绍了如何处理混合类型集合的反序列化,其中的示例与“序列化和反序列化具有任意类型对象的集合”一节中的示例类似。

jdg4fx2g

jdg4fx2g2#

首先,我认为你在上面的例子中可能是错误的。一个由三个不同的数组组成的数组是一个非常不寻常的方法,至少可以说。可能你的json结构是一个数组,包含元组。这些元组然后包括一个数组。
如:

[
{
    "hello",
    1,
    [2]
},
{
    "world",
    3,
    [2]
}
]

XXX应该是包含以下内容的对象:
A字符串
一个整型(或整数)
一个(我猜是)整型数组。
然后创建这些对象的数组,并将json解析到其中。
但是,您的json似乎真的格式很差,因为所有成员都应该命名为

[
{
    "str":"hello",
    "intVal":1,
    "intArr":[2]
},
{
    "str":"world",
    "intVal":3,
    "intArr":[2]
}
]

另一方面,如果JSON真的如您所描述的那样,那么您就必须创建简单明了的Object数组,然后在从数据结构中读取它们时对其进行转换。

相关问题