Jersey/Genson: 正在解组单个对象数组
Jersey/Genson: Unmarschalling single object array
类似于 Jersey: Json array with 1 element is serialized as object 但在客户端。例如。我收到一个 JSON 对象,其中一个字段是一个数组,但如果只有一个元素,它就是一个对象。
{"fileInfo":[{"fileName":"weather.arff","id":"10"},"fileName":"supermarket.arff","id":"11"}]}
对比
{"fileInfo":{"fileName":"weather.arff","id":"10"}}
我是 parsing/unmarshalling JSON 使用 Jersey/Genson。当然,如果 JSON 与目标 class 不匹配,我会收到错误消息(例如 expected [ but read '{'
)
我已经阅读了很多关于这个错误以及在服务器端创建 JSON 对象时如何避免的内容,但是我没有发现在客户端处理时如何处理这个问题。
一如既往,如果有多种解决方案,我更喜欢最无代码的可能性...
顺便说一句:Moxy 可以工作,但它不会编组本机对象类型对象,这是另一个要求...
更新
从 Genson 1.3 release 开始,您可以通过启用 permissiveParsing 来实现它:
Genson genson = new GensonBuilder().usePermissiveParsing(true).create();
回答
呃,你知道服务器端生成这个的库是什么吗?我很好奇谁对所有那些结构不良的人负责 json...
Genson 尚不支持它。本来是因为IMO的人不应该产生这样的动态json。无论如何,我打开了 an issue - 这很容易完成,你可以期待它出现在下周发布的版本中。
否则这里有一种不破坏现有机制的实现方式。
您需要注册一个工厂,它将使用 Gensons 集合工厂来创建其标准集合转换器的实例。然后将此转换器包装在另一个将对象处理为数组逻辑的转换器中。这是代码(不是无代码......,但如果你稍等一下,你就不必编码 :))。
import com.owlike.genson.convert.DefaultConverters.CollectionConverterFactory;
import com.owlike.genson.convert.DefaultConverters.CollectionConverterFactory;
class SingleObjectAsCollectionFactory implements Factory<Converter<Collection>> {
// get the default factory
Factory<Converter<Collection<?>>> defaultFactory = CollectionConverterFactory.instance;
@Override
public Converter<Collection> create(Type type, Genson genson) {
// obtain an instance of the correct default converter for this type
final CollectionConverter defaultConverter = (CollectionConverter) defaultFactory.create(type, genson);
// wrap it in your own converter
return new Converter<Collection>() {
@Override
public void serialize(Collection object, ObjectWriter writer, Context ctx) throws Exception {
defaultConverter.serialize(object, writer, ctx);
}
@Override
public Collection deserialize(ObjectReader reader, Context ctx) throws Exception {
if (reader.getValueType() == ValueType.OBJECT) {
Object object = defaultConverter.getElementConverter().deserialize(reader, ctx);
Collection result = defaultConverter.create();
result.add(object);
return result;
} else return defaultConverter.deserialize( reader, ctx );
}
};
}
}
然后注册
Genson genson = new GensonBuilder()
.withConverterFactory(new SingleObjectAsCollectionFactory())
.create();
类似于 Jersey: Json array with 1 element is serialized as object 但在客户端。例如。我收到一个 JSON 对象,其中一个字段是一个数组,但如果只有一个元素,它就是一个对象。
{"fileInfo":[{"fileName":"weather.arff","id":"10"},"fileName":"supermarket.arff","id":"11"}]}
对比
{"fileInfo":{"fileName":"weather.arff","id":"10"}}
我是 parsing/unmarshalling JSON 使用 Jersey/Genson。当然,如果 JSON 与目标 class 不匹配,我会收到错误消息(例如 expected [ but read '{'
)
我已经阅读了很多关于这个错误以及在服务器端创建 JSON 对象时如何避免的内容,但是我没有发现在客户端处理时如何处理这个问题。
一如既往,如果有多种解决方案,我更喜欢最无代码的可能性...
顺便说一句:Moxy 可以工作,但它不会编组本机对象类型对象,这是另一个要求...
更新
从 Genson 1.3 release 开始,您可以通过启用 permissiveParsing 来实现它:
Genson genson = new GensonBuilder().usePermissiveParsing(true).create();
回答
呃,你知道服务器端生成这个的库是什么吗?我很好奇谁对所有那些结构不良的人负责 json...
Genson 尚不支持它。本来是因为IMO的人不应该产生这样的动态json。无论如何,我打开了 an issue - 这很容易完成,你可以期待它出现在下周发布的版本中。
否则这里有一种不破坏现有机制的实现方式。 您需要注册一个工厂,它将使用 Gensons 集合工厂来创建其标准集合转换器的实例。然后将此转换器包装在另一个将对象处理为数组逻辑的转换器中。这是代码(不是无代码......,但如果你稍等一下,你就不必编码 :))。
import com.owlike.genson.convert.DefaultConverters.CollectionConverterFactory;
import com.owlike.genson.convert.DefaultConverters.CollectionConverterFactory;
class SingleObjectAsCollectionFactory implements Factory<Converter<Collection>> {
// get the default factory
Factory<Converter<Collection<?>>> defaultFactory = CollectionConverterFactory.instance;
@Override
public Converter<Collection> create(Type type, Genson genson) {
// obtain an instance of the correct default converter for this type
final CollectionConverter defaultConverter = (CollectionConverter) defaultFactory.create(type, genson);
// wrap it in your own converter
return new Converter<Collection>() {
@Override
public void serialize(Collection object, ObjectWriter writer, Context ctx) throws Exception {
defaultConverter.serialize(object, writer, ctx);
}
@Override
public Collection deserialize(ObjectReader reader, Context ctx) throws Exception {
if (reader.getValueType() == ValueType.OBJECT) {
Object object = defaultConverter.getElementConverter().deserialize(reader, ctx);
Collection result = defaultConverter.create();
result.add(object);
return result;
} else return defaultConverter.deserialize( reader, ctx );
}
};
}
}
然后注册
Genson genson = new GensonBuilder()
.withConverterFactory(new SingleObjectAsCollectionFactory())
.create();