我有一群具有类型的字段的模型类的List<X>
地方X
是很多的事情之一(例如String
,Integer
,但也有一些我自己的类型)。我正在使用GSON解析这些模型的JSON表示形式。
我的问题是,我正在处理的服务器(超出我的控制范围)以某种方式删除了单例数组,并将其替换为包含的对象。
例如,不返回:
{
"foo": [ "bar"],
"bleh": [ { "some": "object" } ]
}
它返回:
{
"foo": "bar",
"bleh": { "some": "object" }
}
现在假设Java模型类看起来像这样:
public class Model {
private List<String> foo;
private List<SomeObject> bleh;
}
当前,这会导致GSON抛出异常,因为它找到了BEGIN_STRING
或BEGIN_OBJECT
期望到了什么地方BEGIN_ARRAY
。
对于字符串数组或字符串列表,可以使用轻松解决TypeAdapter<List<String>>
。但是问题是我有List
许多不同的元素类型,并且我不想TypeAdapter
为每种情况编写单独的元素。我也无法使用泛型TypeAdapter<List<?>>
,因为在某些时候您需要知道类型。那么,还有另一种方法可以将GSON配置为足够聪明,以将单个对象或值转换为数组/列表吗?或者换句话说,只是“假装”
the [
and ]
在那里,尽管它们不在那里,但它期望找到它们?
但是问题是我的List具有许多不同的元素类型,并且我不想为每种情况编写单独的TypeAdapter。我也无法使用通用的TypeAdapter>,因为在某些时候您需要知道类型。
这就是类型适配器工厂设计的目的:您可以控制Gson
实例配置中的每种类型。
final class AlwaysListTypeAdapterFactory<E>
implements TypeAdapterFactory {
// Gson can instantiate it itself
private AlwaysListTypeAdapterFactory() {
}
@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
// If it's not a List -- just delegate the job to Gson and let it pick the best type adapter itself
if ( !List.class.isAssignableFrom(typeToken.getRawType()) ) {
return null;
}
// Resolving the list parameter type
final Type elementType = resolveTypeArgument(typeToken.getType());
@SuppressWarnings("unchecked")
final TypeAdapter<E> elementTypeAdapter = (TypeAdapter<E>) gson.getAdapter(TypeToken.get(elementType));
// Note that the always-list type adapter is made null-safe, so we don't have to check nulls ourselves
@SuppressWarnings("unchecked")
final TypeAdapter<T> alwaysListTypeAdapter = (TypeAdapter<T>) new AlwaysListTypeAdapter<>(elementTypeAdapter).nullSafe();
return alwaysListTypeAdapter;
}
private static Type resolveTypeArgument(final Type type) {
// The given type is not parameterized?
if ( !(type instanceof ParameterizedType) ) {
// No, raw
return Object.class;
}
final ParameterizedType parameterizedType = (ParameterizedType) type;
return parameterizedType.getActualTypeArguments()[0];
}
private static final class AlwaysListTypeAdapter<E>
extends TypeAdapter<List<E>> {
private final TypeAdapter<E> elementTypeAdapter;
private AlwaysListTypeAdapter(final TypeAdapter<E> elementTypeAdapter) {
this.elementTypeAdapter = elementTypeAdapter;
}
@Override
public void write(final JsonWriter out, final List<E> list) {
throw new UnsupportedOperationException();
}
@Override
public List<E> read(final JsonReader in)
throws IOException {
// This is where we detect the list "type"
final List<E> list = new ArrayList<>();
final JsonToken token = in.peek();
switch ( token ) {
case BEGIN_ARRAY:
// If it's a regular list, just consume [, <all elements>, and ]
in.beginArray();
while ( in.hasNext() ) {
list.add(elementTypeAdapter.read(in));
}
in.endArray();
break;
case BEGIN_OBJECT:
case STRING:
case NUMBER:
case BOOLEAN:
// An object or a primitive? Just add the current value to the result list
list.add(elementTypeAdapter.read(in));
break;
case NULL:
throw new AssertionError("Must never happen: check if the type adapter configured with .nullSafe()");
case NAME:
case END_ARRAY:
case END_OBJECT:
case END_DOCUMENT:
throw new MalformedJsonException("Unexpected token: " + token);
default:
throw new AssertionError("Must never happen: " + token);
}
return list;
}
}
}
现在,您只需要告诉Gson 哪些
字段格式不正确。当然,您可以将整个Gson
实例配置为接受此类列表,但是使用@JsonAdapter
批注使其更为精确:
final class Model {
@JsonAdapter(AlwaysListTypeAdapterFactory.class)
final List<String> foo = null;
@JsonAdapter(AlwaysListTypeAdapterFactory.class)
final List<SomeObject> bleh = null;
@Override
public String toString() {
return "Model{" + "foo=" + foo + ", bleh=" + bleh + '}';
}
}
final class SomeObject {
final String some = null;
@Override
public String toString() {
return "SomeObject{" + "some='" + some + '\'' + '}';
}
}
测试数据:
{
"foo": "bar",
"bleh": {"some": "object"}
}
{
"foo": ["bar"],
"bleh": [{"some": "object"}]
}
例:
private static final Gson gson = new Gson();
public static void main(final String... args)
throws IOException {
for ( final String resource : ImmutableList.of("single.json", "list.json") ) {
try ( final JsonReader jsonReader = getPackageResourceJsonReader(Q43412261.class, resource) ) {
final Model model = gson.fromJson(jsonReader, Model.class);
System.out.println(model);
}
}
}
并输出:
模型{foo = [bar],bleh = [SomeObject {some =’object’}]}}
模型{foo = [bar],bleh = [SomeObject {some =’object’}]}}
我有许多模型类,它们的字段类型为,其中是许多类型之一(例如、,还有一些我自己的类型)。我正在使用GSON解析这些模型的JSON表示。 我的问题是,我正在处理的服务器(这超出了我的控制范围)不知何故删除了单例数组,并用包含的对象替换它们。 例如,不返回:
请编写一个名为lastElement的函数,该函数接受单个数组参数。函数应返回数组的最后一个元素(不删除该元素)。如果数组为空,则函数应返回null。 lastElement([3,5,7])//7 lastElement([1])//1 lastElement([])//null 我对最后一部分感到困惑,如果数组为空,函数将返回null。
我正试图从这个服务器响应中提取“级别”。我对Android开发有点陌生。我需要帮助解析这个API响应到一个POJO列表。 级别的kotlin数据类:
问题内容: 在Angular中,我在范围内有一个对象,该对象返回许多对象。每个都有一个ID(此ID存储在一个平面文件中,因此没有DB,而且我似乎无法使用) 在我的控制器中: 在我看来,我还有关于默认隐藏的鱼类的更多附加信息,但是当我单击简单的显示更多标签时,我想调用该函数。我的函数看起来像: 现在,在视图中将显示更多详细信息。但是,在搜索了文档之后,我无法弄清楚如何搜索该数组。 那么如何查询数组?
我刚到爪哇。我正在学习将图像和其他数据从db检索到JTable的教程。数据将首先检索到ArrayList中,我得到了一个错误,说array是必需的,但object是找到的。我已经添加了我所有的代码。错误在文件中。如有任何帮助,不胜感激。 course.java
打完电话后 我只填充了的和。列表始终保持。我怎么才能修好这个?