如何构造 class 来反序列化这个嵌套数组?
How to structure class for deserializing this nested array?
我正在尝试从 JSON 响应中反序列化嵌套数组。这是我第一次得到一个数组数组,我不太确定如何构建我的 class 来处理它。
{
"prices": [
[
1641670404234,
0.01582586939240936
],
[
1641674037525,
0.015999047707867396
],
[
1641677655158,
0.016072905257982606
]
...
],
}
如果括号是 {
而不是 [
{
"prices": {
{
1641670404234,
0.01582586939240936
},
{
1641674037525,
0.015999047707867396
},
{
1641677655158,
0.016072905257982606
}
}
...
}
我可以用
@SerializedName("prices")
private List<Price> prices;
public class Price {
private long date;
private BigDecimal price;
}
但是因为它是 [
,所以我不确定如何构造它。
我试过向它添加另一个 List
包装器,但这会引发错误
@SerializedName("prices")
private List<List<Price>> prices;
IllegalStateException: Expected BEGIN_OBJECT but was NUMBER at line 1 column 26 path $.prices[0][0]
我也试过用JSONArray
包裹它
@SerializedName("prices")
private List<JSONArray<Price>> prices;
但这不太对
我尝试搜索其他 SO 答案,但找不到任何包含两个连续 [ [
括号的示例。
他们都是{ [
或[ {
。
正确的做法是什么?
假设这是正确的JSON:
{
"prices": [
[
1641670404234,
0.01582586939240936
],
[
1641674037525,
0.015999047707867396
],
[
1641677655158,
0.016072905257982606
]
]
}
然后您可以使用此模型将数据反序列化为:
JAVA:
public class PricesModel {
public ArrayList<ArrayList<Double>> prices;
}
KOTLIN:
data class PricesModel (
@SerializedName("prices" ) var prices : ArrayList<ArrayList<Double>> = arrayListOf()
)
解决此问题的正确方法是为您的 Price
class 编写自定义 TypeAdapter
。这样做的好处是您可以保持模型 class 原样(带有 List<Price> prices
字段),并让它们更接近实际数据。相反,如果您将 JSON 数据解析为 List<List<BigDecimal>>
或类似数据,则您必须手动验证 JSON 数据是否格式正确,并且必须将 List<BigDecimal>
转换为 Price
反对你自己。
TypeAdapter
Price
class 的实现如下所示:
class PriceTypeAdapter extends TypeAdapter<Price> {
@Override
public void write(JsonWriter out, Price value) throws IOException {
out.beginArray();
out.value(value.date);
out.value(value.price);
out.endArray();
}
@Override
public Price read(JsonReader in) throws IOException {
in.beginArray();
Price priceObj = new Price();
priceObj.date = in.nextLong();
// nextString() automatically converts JSON numbers to String, if necessary
// This is similar to how Gson's default adapter for BigDecimal works
priceObj.price = new BigDecimal(in.nextString());
in.endArray();
return priceObj;
}
}
注意:除了如此处所示手动读取 BigDecimal
,您可以在 TypeAdapterFactory
中创建此类型的适配器并获取 BigDecimal
的默认 Gson 适配器。这允许在您自己的类型适配器中重用 Gson 的内置适配器,但是对于 BigDecimal
来说,这种开销可能不值得。
然后您可以在其上 register your adapter on a GsonBuilder
instance or you can place an @JsonAdapter
annotation on your Price
class, which references the adapter. In case you use the GsonBuilder
approach, you might want to create a null
-safe variant of your adapter by calling nullSafe()
(或者您在适配器中手动实现 null
处理)。
我正在尝试从 JSON 响应中反序列化嵌套数组。这是我第一次得到一个数组数组,我不太确定如何构建我的 class 来处理它。
{
"prices": [
[
1641670404234,
0.01582586939240936
],
[
1641674037525,
0.015999047707867396
],
[
1641677655158,
0.016072905257982606
]
...
],
}
如果括号是 {
而不是 [
{
"prices": {
{
1641670404234,
0.01582586939240936
},
{
1641674037525,
0.015999047707867396
},
{
1641677655158,
0.016072905257982606
}
}
...
}
我可以用
@SerializedName("prices")
private List<Price> prices;
public class Price {
private long date;
private BigDecimal price;
}
但是因为它是 [
,所以我不确定如何构造它。
我试过向它添加另一个 List
包装器,但这会引发错误
@SerializedName("prices")
private List<List<Price>> prices;
IllegalStateException: Expected BEGIN_OBJECT but was NUMBER at line 1 column 26 path $.prices[0][0]
我也试过用JSONArray
@SerializedName("prices")
private List<JSONArray<Price>> prices;
但这不太对
我尝试搜索其他 SO 答案,但找不到任何包含两个连续 [ [
括号的示例。
他们都是{ [
或[ {
。
正确的做法是什么?
假设这是正确的JSON:
{
"prices": [
[
1641670404234,
0.01582586939240936
],
[
1641674037525,
0.015999047707867396
],
[
1641677655158,
0.016072905257982606
]
]
}
然后您可以使用此模型将数据反序列化为:
JAVA:
public class PricesModel {
public ArrayList<ArrayList<Double>> prices;
}
KOTLIN:
data class PricesModel (
@SerializedName("prices" ) var prices : ArrayList<ArrayList<Double>> = arrayListOf()
)
解决此问题的正确方法是为您的 Price
class 编写自定义 TypeAdapter
。这样做的好处是您可以保持模型 class 原样(带有 List<Price> prices
字段),并让它们更接近实际数据。相反,如果您将 JSON 数据解析为 List<List<BigDecimal>>
或类似数据,则您必须手动验证 JSON 数据是否格式正确,并且必须将 List<BigDecimal>
转换为 Price
反对你自己。
TypeAdapter
Price
class 的实现如下所示:
class PriceTypeAdapter extends TypeAdapter<Price> {
@Override
public void write(JsonWriter out, Price value) throws IOException {
out.beginArray();
out.value(value.date);
out.value(value.price);
out.endArray();
}
@Override
public Price read(JsonReader in) throws IOException {
in.beginArray();
Price priceObj = new Price();
priceObj.date = in.nextLong();
// nextString() automatically converts JSON numbers to String, if necessary
// This is similar to how Gson's default adapter for BigDecimal works
priceObj.price = new BigDecimal(in.nextString());
in.endArray();
return priceObj;
}
}
注意:除了如此处所示手动读取 BigDecimal
,您可以在 TypeAdapterFactory
中创建此类型的适配器并获取 BigDecimal
的默认 Gson 适配器。这允许在您自己的类型适配器中重用 Gson 的内置适配器,但是对于 BigDecimal
来说,这种开销可能不值得。
然后您可以在其上 register your adapter on a GsonBuilder
instance or you can place an @JsonAdapter
annotation on your Price
class, which references the adapter. In case you use the GsonBuilder
approach, you might want to create a null
-safe variant of your adapter by calling nullSafe()
(或者您在适配器中手动实现 null
处理)。