gpt4 book ai didi

java - 对Jackson使用非JSON格式

转载 作者:行者123 更新时间:2023-11-30 10:27:38 25 4
gpt4 key购买 nike

我正在使用JAX-RS(带有RESTEasy)和最新版本的Jackson来编组JSON中的对象。例如,我仅将返回内容类型指定为application/json,然后将我的对象转换为JSON。我可以使用Jackson注释来调整哪些属性被序列化,如何命名等。

我有一个基于文本的自定义Foo格式text/foo(出于讨论的目的),它类似于JSON但有所不同,尤其是在对象和属性定界的方式中。我希望能够将text/foo指定为返回内容类型,并使我的对象自动序列化为Foo格式。我希望我的封送处理库独立于JAX-RS实现。

我的第一个想法是以某种方式利用Jackson,以便我可以利用Jackson的属性名称注释等。这样,如果我将内容类型更改为text/foo,则使用Jackson为JSON配置的某些对象将是序列化为Foo格式,但仍使用Jackson批注指示的属性名称。

Jackson变得非常复杂,具有各种API,并且从哪里开始并不明显。


是否可以利用Jackson将对象序列化为非JSON格式?
我应该使用哪个Jackson API(树模型,流API或数据绑定)?
是否有一些现有的非JSON Jackson库可以作为示例来帮助我入门?
以这种方式使用Jackson只会带来更多麻烦,而我应该只编写JAX-RS MessageBodyReaderMessageBodyWriter实现,而完全跳过Jackson吗? (我犹豫要走这条路,因为我必须从头开始编写所有反射逻辑,编写我自己的注释以指定属性名称更改等,并放弃所有Jackson的类型插件基础结构。)

最佳答案

Jackson API的优势


是可用于处理JSON文件的最快的库之一。
具有更广泛的注释支持,甚至可以接受来自其他API(例如JAXB)的注释。
与JAX-RS有更好的集成。


流式(核心)

这是杰克逊(Jackson)的核心,是解析器/序列化器停留的地方,用于处理输入/输出数据的流。


这是可用于解析/序列化数据的最快方法。
这不是处理JSON内容的最便捷方法。


必须以与输入/输出完全相同的顺序处理内容,即不能随机访问。
中间件和框架使用更多,但对于应用程序不是很常见。



这是必须具有完整功能版本的Jackson的API,该版本支持所需的数据格式。它也是由其他数据格式(例如XML,Java属性,YAML等)实现的唯一API。

实现此API后,将自动支持DataBinding和TreeModel。

GSON也与Jackson一起进行了研究,但由于与Jackson相似且缺乏性能,因此Jackson是本报告的主要主题。

性能的差异是由于这些API处理数据的方式所致,Jackson首先使用流,这是一种快速的低级方法,它使Jackson成为启动时处理JSON的最快API。

尽管GSON也已开始使用这种方法来处理数据,但是根据基准测试(根据参考资料部分中的基准测试),杰克逊仍然是最快的API。

树模型

这是api的一部分,它提供了JSON文档的可变内存中树表示形式。

使用某些类似于XML的数据格式时,该API是最灵活的。

数据绑定

这是api的一部分,它基于属性访问器约定或注释将JSON与POJO相互转换。

处理JSON内容的最便捷方法。
它允许在JSON数据和JAVA对象之间进行转换。
与TreeModel相似,但是使用Java对象而不是基于节点的模型。

就应用程序而言,此API是最常用的



有关Jackson流实现的说明

由于这是我们唯一需要实现的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实例一样,换句话说,它伪造了自己的格式,使其看起来像Jackson的Json实例。这不是一个干净的方法。例如,他们可以使用 TYPE_OBJECT来表示类似 <element>value<element>property = "string containing the value of the property."的内容。

这适用于具有与Json相同/更少功能的格式,因为可以实现所有功能,但是具有更多功能的数据格式是不可能的。



该报告是作为 https://globalmentor.atlassian.net/browse/URF-33的一部分为GlobalMentor Inc.编写的,我们在该报告中尝试在Jackson中实施对 SURF data format的支持。

关于java - 对Jackson使用非JSON格式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45242789/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com