我使用JAX-RS(使用RESTEasy)和最新版本的Jackson来编组JSON中的对象。我只是将返回内容类型指定为application/json
,例如,我的对象将转换为JSON。我可以使用Jackson注释来调整哪些属性被序列化,它们是如何命名的等等。
我有一个基于文本的自定义Foo格式text/foo
(为了讨论起见),它类似于JSON但不同,特别是对象和属性的分隔方式。我希望能够将text/foo
指定为返回内容类型,并将我的对象自动序列化为Foo格式。我希望我的编组库独立于JAX-RS实现。
我的第一个想法是以某种方式利用杰克逊,以便我可以利用杰克逊对属性名称等的注释。这样,如果我改变了内容,那么使用杰克逊为JSON配置的一些对象就会键入text/foo
,序列化为Foo格式,但仍然使用Jackson注释指示的属性名称。
杰克逊证明是相当复杂的,有各种各样的API,并且从哪里开始并不明显。
MessageBodyReader
和MessageBodyWriter
实现,完全跳过Jackson? (我不愿意走这条路,因为我必须从头开始编写所有反射逻辑,编写我自己的注释以指定属性名称更改等,并放弃Jackson的所有类型插件基础结构。)答案 0 :(得分:1)
Jackson API的优势
流媒体(核心)
这是Jackson的核心,它是解析器/序列化器所在的位置,处理输入/输出数据的流式传输。
这是我们必须实现的API,以便拥有支持我们想要的数据格式的Jackson的完整功能版本。它也是由XML,Java Properties,YAML等其他数据格式实现的唯一API。
实施此API后,将自动支持DataBinding和TreeModel。
GSON也与杰克逊一起学习,但由于杰克逊与杰克逊的相似性及其缺乏表现,杰克逊是本报告的主题。
性能的差异是由于这些API处理数据的方式,Jackson首先使用流,这是一种快速的低级方法,它使Jackson成为使用JSON处理的最快的API什么时候推出。
尽管GSON也开始使用这种方法来处理数据,但杰克逊仍然是最快的API,根据基准测试可能会在参考部分找到。
<强>的TreeModel 强>
这是api的一部分,它提供了JSON文档的可变内存树表示。
使用类似于XML的某种数据格式处理时,此API是最灵活的。
<强>数据绑定强>
这是api的一部分,它根据属性访问器约定或注释将POSON转换为POJO和从POJO转换。
处理JSON内容的最便捷方式。 它允许在JSON数据和JAVA对象之间进行转换。 与TreeModel类似,但使用Java对象而不是基于节点的模型。
此API在应用程序方面最常用
关于杰克逊流媒体实施的说明
由于这是我们需要实施的唯一API,因此我们将更加关注此问题。
Streaming API的实现使用所谓的JsonToken
来识别流中即将出现的JSON对象,即输入/输出数据。
JsonToken
枚举具有以下定义:
NOT_AVAILABLE(null),
START_OBJECT("{"),
END_OBJECT("}"),
START_ARRAY("["),
END_ARRAY("]"),
FIELD_NAME(null),
VALUE_STRING(null),
VALUE_NUMBER_INT(null),
VALUE_NUMBER_FLOAT(null),
VALUE_TRUE("true"),
VALUE_FALSE("false"),
VALUE_NULL("null")
这些令牌可以通过所谓的ReadContext
来检索。 ReadContext
有一些常量来定义自己的类型。
内部使用的常量表示JsonStreamContext
类型。
protected final static int TYPE_ROOT = 0; // Means the root element.
protected final static int TYPE_ARRAY = 1; // Means the array elements.
protected final static int TYPE_OBJECT = 2; // Means the JSON object elements.
Java属性数据格式的ReadContext构造函数方法的片段。
JPropReadContext extends JsonStreamContext {
// Static factory method used to create the JPropReadContext instance.
public static JPropReadContext create(JPropNode root) {
if (root.isArray()) { // can this ever occur?
return new ArrayContext(null, root);
}
return new ObjectContext(null, root);
}
…
ArrayContext extends JPropReadContext {
// Constructor for ArrayContext.
public ArrayContext(JPropReadContext p, JPropNode arrayNode) {
super(JsonStreamContext.TYPE_ARRAY, p, arrayNode);
_contents = arrayNode.arrayContents();
_state = STATE_START;
}
…
}
…
ObjectContext extends JPropReadContext {
// Constructor for ObjectContext.
public ObjectContext(JPropReadContext p, JPropNode objectNode) {
super(JsonStreamContext.TYPE_OBJECT, p, objectNode);
_contents = objectNode.objectContents();
_state = STATE_START;
}
…
}
…
}
JPropReadContext
仅扩展JsonStreamContext
,因此它需要从JsonStreamContext
传递一个常量,指示上下文的类型,如果它是根,数组或对象。常量是一个简单的int值,所以在那之前没问题。
以下是相同的信息,但现在是XML数据格式。
…
// Static factory method used to create the XmlReadContext instance of type ROOT.
public static XmlReadContext createRootContext(int lineNr, int colNr) {
return new XmlReadContext(null, TYPE_ROOT, lineNr, colNr);
}
// Static factory method used to create the XmlReadContext instance of type ARRAY.
public final XmlReadContext createChildArrayContext(int lineNr, int colNr) {
XmlReadContext ctxt = _child;
if (ctxt == null) {
_child = ctxt = new XmlReadContext(this, TYPE_ARRAY, lineNr, colNr);
return ctxt;
}
ctxt.reset(TYPE_ARRAY, lineNr, colNr);
return ctxt;
}
// Static factory method used to create the XmlReadContext instance of type OBJECT.
public final XmlReadContext createChildObjectContext(int lineNr, int colNr) {
XmlReadContext ctxt = _child;
if (ctxt == null) {
_child = ctxt = new XmlReadContext(this, TYPE_OBJECT, lineNr, colNr);
return ctxt;
}
ctxt.reset(TYPE_OBJECT, lineNr, colNr);
return ctxt;
}
…
Jackson的其他数据格式的实现只是使用这些常量和JsonToken
,就好像它们的格式是Json实例一样,换句话说,它伪造自己的格式使其看起来像Json杰克逊的例子,这不是一个干净的方式。例如,他们可以使用TYPE_OBJECT
来表示<element>value<element>
或property = "string containing the value of the property."
之类的内容。
这适用于与Json具有相同/更少功能的格式,因为每个功能都可以实现,但是对于具有比这更多功能的数据格式是不可能的。
此报告是作为https://globalmentor.atlassian.net/browse/URF-33的一部分为GlobalMentor Inc.制作的,我们尝试在杰克逊中实施对SURF data format的支持。