<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>绿色记忆 &#187; JSON</title>
	<atom:link href="https://blog.gmem.cc/tag/json/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.gmem.cc</link>
	<description></description>
	<lastBuildDate>Mon, 06 Apr 2026 12:46:48 +0000</lastBuildDate>
	<language>en-US</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.9.14</generator>
	<item>
		<title>使用Jansson处理JSON</title>
		<link>https://blog.gmem.cc/json-processing-with-jansson</link>
		<comments>https://blog.gmem.cc/json-processing-with-jansson#comments</comments>
		<pubDate>Thu, 31 Aug 2017 04:36:06 +0000</pubDate>
		<dc:creator><![CDATA[Alex]]></dc:creator>
				<category><![CDATA[C]]></category>
		<category><![CDATA[JSON]]></category>

		<guid isPermaLink="false">https://blog.gmem.cc/?p=15678</guid>
		<description><![CDATA[<p>简介 Jansson是一个用于解码、编码、操控JSON的C库。其特性为： 简单直观的API和数据模型 没有依赖项 完整的Unicode支持（UTF-8） 构建 Jansson使用cmake作为构建工具。可以执行下面的命令构建： [crayon-69d78ef9d2847979527572/] 上述命令执行后，Jansson的头文件和静态库被安装到/home/alex/CPP/lib/jansson/2.9目录 使用 这里我们创建一个CMake工程： [crayon-69d78ef9d284f365280566/] 解码JSON 下面的代码展示了如何把字符串解码为json_t结构： [crayon-69d78ef9d2853078509195/] 运行上述代码后输出： [crayon-69d78ef9d2856075057963/] 编码JSON 下面的代码展示了如何把json_t结构编码为字符串： [crayon-69d78ef9d285a863035774/] 运行上述代码后输出： [crayon-69d78ef9d285c535339608/] <a class="read-more" href="https://blog.gmem.cc/json-processing-with-jansson">[...]</a></p>
<p>The post <a rel="nofollow" href="https://blog.gmem.cc/json-processing-with-jansson">使用Jansson处理JSON</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></description>
				<content:encoded><![CDATA[<div class="wri_content_clear_both"><div class="blog_h2"><span class="graybg">简介</span></div>
<p><a href="http://www.digip.org/jansson/">Jansson</a>是一个用于解码、编码、操控JSON的C库。其特性为：</p>
<ol>
<li>简单直观的API和数据模型</li>
<li>没有依赖项</li>
<li>完整的Unicode支持（UTF-8）</li>
</ol>
<div class="blog_h2"><span class="graybg">构建</span></div>
<p>Jansson使用cmake作为构建工具。可以执行下面的命令构建：</p>
<pre class="crayon-plain-tag">git clone https://github.com/akheron/jansson
cd jansson
mkdir build &amp;&amp; cd build
cmake -DCMAKE_INSTALL_PREFIX:STRING=/home/alex/CPP/lib/jansson/2.9 -DJANSSON_BUILD_DOCS=OFF ..
cmake --build . -- install</pre>
<p>上述命令执行后，Jansson的头文件和静态库被安装到/home/alex/CPP/lib/jansson/2.9目录</p>
<div class="blog_h2"><span class="graybg">使用</span></div>
<p>这里我们创建一个CMake工程：</p>
<pre class="crayon-plain-tag">cmake_minimum_required(VERSION 3.6)
project(jansson_demo C)
set(SOURCE_FILES main.c)
include_directories(/home/alex/CPP/lib/jansson/2.9/include)
add_executable(jansson_demo ${SOURCE_FILES})
set_property(TARGET jansson_demo PROPERTY C_STANDARD 99)
target_link_libraries(jansson_demo /home/alex/CPP/lib/jansson/2.9/lib/libjansson.a)</pre>
<div class="blog_h3"><span class="graybg">解码JSON</span></div>
<p>下面的代码展示了如何把<span style="background-color: #c0c0c0;">字符串解码为json_t</span>结构：</p>
<pre class="crayon-plain-tag">#include &lt;jansson.h&gt;
#include &lt;assert.h&gt;

int main() {
    char *text = "{ \"name\":\"汪震\", \"age\":30, \"children\":[ \"彩彩\", \"当当\" ] }";
    json_error_t error;
    // json_t用于引用任何JSON节点
    json_t *root = json_loads( text, 0, &amp;error );
    // 如果读取失败，自动置为空指针
    if ( !root ) {
        fprintf( stderr, "error: on line %d: %s\n", error.line, error.text );
        return 1;
    } else {
        // json_is_*宏用于判断数据类型
        // 处理JSON对象
        assert( json_is_object( root ));
        json_t *name, *age, *children;
        name = json_object_get( root, "name" );
        age = json_object_get( root, "age" );
        fprintf( stdout, "NAME: %s, AGE: %d\n", json_string_value( name ), json_integer_value( age ));
        children = json_object_get( root, "children" );
        // 处理JSON数组
        assert( json_is_array( children ));
        int sof = json_array_size( children );
        for ( int i = 0; i != sof; i++ ) {
            json_t *child = json_array_get( children, i );
            fprintf( stdout, "CHILDREN: %s\n", json_string_value( child ));
        }
        // 减小引用计数，导致资源回收
        json_decref( root );
    }
    return 0;
}</pre>
<p>运行上述代码后输出：</p>
<pre class="crayon-plain-tag">NAME: 汪震, AGE: 30
CHILDREN: 彩彩
CHILDREN: 当当</pre>
<div class="blog_h3">
<div class="blog_h3"><span class="graybg">编码JSON</span></div>
</div>
<p>下面的代码展示了如何把<span style="background-color: #c0c0c0;">json_t结构编码为字符串</span>：</p>
<pre class="crayon-plain-tag">json_t *root = json_pack( "{sssis[ss]}", "name", "汪震", "age", 30, "children", "彩彩", "当当" );
char *text = json_dumps( root, JSON_INDENT( 4 ) | JSON_SORT_KEYS );
fprintf( stdout, "%s\n", text );</pre>
<p>运行上述代码后输出：</p>
<pre class="crayon-plain-tag">{
    "age": 30,
    "children": [
        "彩彩",
        "当当"
    ],
    "name": "汪震"
}</pre>
<div class="blog_h3"><span class="graybg">打包JSON</span></div>
<p>下面的代码展示了如何把<span style="background-color: #c0c0c0;">零散数据打包（pack）为json_t</span>结构：</p>
<pre class="crayon-plain-tag">assert( json_is_integer( json_pack( "i", 1 )));
assert( json_is_array(
        // jansson使用格式限定符来指定要创建的JSON的JSON节点的类型
        // 下面的例子创建三元素的数组：字符串、字符串、布尔值
        json_pack( "[ssb]", "foo", "bar", 1 )
));
/* 打包一个空对象 */
json_pack( "{}" );
/* 打包出 {age:30,childNum:2} */
json_pack( "{sisi}", "age", 30, "childNum", 2 );
/* 打包出 [[1, 2], {"num": true}] */
json_pack( "[[i,i],{s:b}]", 1, 2, "num", 1 );
return 0;</pre>
<p>可用的格式限定符如下表：</p>
<table class="full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 12%; text-align: center;">限定符</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>s</td>
<td>将null结尾的UTF-8字符串转换为JSON字符串</td>
</tr>
<tr>
<td>s?</td>
<td>和上面类似，但是如果位置参数是NULL则插入JSON null值</td>
</tr>
<tr>
<td>s#</td>
<td>对应两个位置参数const char *, int，将指定长度的UTF-8缓冲转换为JSON字符串</td>
</tr>
<tr>
<td>s%</td>
<td>和上面类似，只是未知参数类型为const char *, size_t</td>
</tr>
<tr>
<td>+</td>
<td>把此位置参数连接到前一个位置参数后面</td>
</tr>
<tr>
<td>+#</td>
<td>和上面类似，接收位置参数const char *, int</td>
</tr>
<tr>
<td>+%</td>
<td>和上面类似，接收位置参数const char *, size_t</td>
</tr>
<tr>
<td>n</td>
<td>输出null，不消耗位置参数 </td>
</tr>
<tr>
<td>b </td>
<td>转换int为JSON布尔值</td>
</tr>
<tr>
<td>i </td>
<td>转换int为JSON整数</td>
</tr>
<tr>
<td>I </td>
<td>转换json_int_t为JSON整数</td>
</tr>
<tr>
<td>f</td>
<td>转换double为JSON实数 </td>
</tr>
<tr>
<td>o</td>
<td>原样插入json_t*结构</td>
</tr>
<tr>
<td>O </td>
<td>和上面类似，但是目标json_t的引用计数会增加</td>
</tr>
<tr>
<td> o?     o?</td>
<td>类似上面两个，但是当位置参数为NULL时插入null</td>
</tr>
<tr>
<td>[fmt]</td>
<td>使用内部的格式限定符构建一个JSON数组，fmt可以是任意符合要求的格式限定符序列</td>
</tr>
<tr>
<td>{fmt}</td>
<td> 使用内部的格式限定符构建一个JSON对象，fmt可以是任意符合要求的格式限定符序列</td>
</tr>
</tbody>
</table>
<div class="blog_h3"><span class="graybg">解包JSON</span></div>
<p>下面的代码展示了如何把<span style="background-color: #c0c0c0;">json_t结构解包为零散数据</span>： </p>
<pre class="crayon-plain-tag">json_t *root = json_pack( "{sssis[ss]}", "name", "汪震", "age", 30, "children", "彩彩", "当当" );
char *name;
int age;
// 可以仅仅解包一部分
json_unpack( root, "{sssi}", "name", &amp;name, "age", &amp;age );
fprintf( stdout, "NAME: %s, AGE:%d\n", name, age );</pre>
</div><p>The post <a rel="nofollow" href="https://blog.gmem.cc/json-processing-with-jansson">使用Jansson处理JSON</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.gmem.cc/json-processing-with-jansson/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JacksonJson知识集锦</title>
		<link>https://blog.gmem.cc/jacksonjson-faq</link>
		<comments>https://blog.gmem.cc/jacksonjson-faq#comments</comments>
		<pubDate>Sat, 22 Dec 2012 04:42:57 +0000</pubDate>
		<dc:creator><![CDATA[Alex]]></dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[JacksonJSON]]></category>
		<category><![CDATA[JSON]]></category>

		<guid isPermaLink="false">http://blog.gmem.cc/?p=1237</guid>
		<description><![CDATA[<p>基础知识 Jackson JSON 提供了一系列API，便于Java程序读写JSON字符串。它具有强大对数据绑定能力，可以方便的在Java对象和JSON字符串之间进行转换。 创建JSON 从Java对象创建（绑定） 代码示例： [crayon-69d78ef9d2f76761809976/] 从JsonNode树创建 示例代码： [crayon-69d78ef9d2f7c346841414/] 构建JSON流 这种方式很不直观，但是节约内存： [crayon-69d78ef9d2f7e063323135/] 解析JSON 解析JSON流 Jackson提供了一种底层API，允许逐符号的处理JSON： [crayon-69d78ef9d2f80448155816/] 解析为JsonNode树 [crayon-69d78ef9d2f83849031714/] 解析为Java对象（绑定）  [crayon-69d78ef9d2f85011137872/] <a class="read-more" href="https://blog.gmem.cc/jacksonjson-faq">[...]</a></p>
<p>The post <a rel="nofollow" href="https://blog.gmem.cc/jacksonjson-faq">JacksonJson知识集锦</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></description>
				<content:encoded><![CDATA[<div class="wri_content_clear_both"><div class="blog_h1"><span class="graybg">基础知识</span></div>
<p>Jackson JSON 提供了一系列API，便于Java程序读写JSON字符串。它具有强大对数据绑定能力，可以方便的在Java对象和JSON字符串之间进行转换。</p>
<div class="blog_h2"><span class="graybg">创建JSON</span></div>
<div class="blog_h3"><span class="graybg">从Java对象创建（绑定）</span></div>
<p>代码示例：</p>
<pre class="crayon-plain-tag">ObjectMapper mapper = new ObjectMapper();
// 启用缩进，更易读
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
// 输出Map类型时，以键排序
mapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
// 日期对象的默认输出格式
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));

/**
 * Java字段名/属性名到JSON字段的映射策略
 */
mapper.setPropertyNamingStrategy( new PropertyNamingStrategy() {
    public String nameForField( MapperConfig config, AnnotatedField field, String defaultName ) {
        if ( field.getFullName().equals( "cc.gmem.vo.Entity#name" ) )
            return "Entity-Name";
        return super.nameForField( config, field, defaultName );
    }

    public String nameForGetterMethod( MapperConfig config, AnnotatedMethod method, String defaultName ) {
        if ( method.getAnnotated().getDeclaringClass().equals( Entity.class ) &amp;&amp; defaultName.equals( "no" ) )
            return "Entity-No";
        return super.nameForGetterMethod( config, method, defaultName );
    }
} );
// 忽略空属性/字段
mapper.setSerializationInclusion(Include.NON_EMPTY);
// 把entity转换为JSON然后写入标准输出
mapper.writeValue(System.out, entity);</pre>
<div class="blog_h3"><span class="graybg">从JsonNode树创建</span></div>
<p>示例代码：</p>
<pre class="crayon-plain-tag">// 此工厂用于创建JsonNode对象
JsonNodeFactory factory = new JsonNodeFactory( false );
// 此工厂用于创建JSON的生成器、解析器
JsonFactory jsonFactory = new JsonFactory();
// 写入到标准输出
JsonGenerator generator = jsonFactory.createGenerator( System.out );
ObjectMapper mapper = new ObjectMapper();
// 根节点
ObjectNode entity = factory.objectNode();
entity.put( "name", "entityname" );
mapper.writeTree( generator, entity );</pre>
<div class="blog_h3"><span class="graybg">构建JSON流</span></div>
<p>这种方式很不直观，但是节约内存：</p>
<pre class="crayon-plain-tag">JsonFactory factory = new JsonFactory();
JsonGenerator generator = factory.createGenerator(new FileWriter(new File("entity.json")));


generator.writeStartObject();
generator.writeFieldName("name");
generator.writeString("Alex");
generator.writeFieldName("dataset");

generator.writeStartArray();
generator.writeStartObject();
generator.writeStringField("zip", "223442");
generator.writeEndObject();
generator.writeEndArray();
generator.writeEndObject();

generator.close();</pre>
<div class="blog_h2"><span class="graybg">解析JSON</span></div>
<div class="blog_h3"><span class="graybg">解析JSON流</span></div>
<p>Jackson提供了一种底层API，允许逐符号的处理JSON：</p>
<pre class="crayon-plain-tag">JsonFactory factory = new JsonFactory();
JsonParser parser = factory.createParser( "{ addresses: [ { zip: 223442 } ] }" );
// 允许非标准的JSON格式：不带引号的字段名
parser.configure( JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true );
while ( !parser.isClosed() ) {
    // 获取下一个解析得到的记号
    JsonToken token = parser.nextToken();
    // 没有下一个记号，说明解析完毕
    if ( token == null ) break;
    // 寻找名为addresses的字段
    if ( JsonToken.FIELD_NAME.equals( token ) &amp;&amp; "addresses".equals( parser.getCurrentName() ) ) {
        // 期望下一个符号是数组开始
        token = parser.nextToken();
        if ( !JsonToken.START_ARRAY.equals( token ) ) break;
        // 期望下一个符号是对象开始
        token = parser.nextToken();
        if ( !JsonToken.START_OBJECT.equals( token ) ) break;
        while ( true ) {
            token = parser.nextToken();
            if ( token == null ) break;
            if ( JsonToken.FIELD_NAME.equals( token ) &amp;&amp; "zip".equals( parser.getCurrentName() ) ) {
                token = parser.nextToken();
                System.out.println( parser.getText() );
            }

        }

    }

}</pre>
<div class="blog_h3"><span class="graybg">解析为JsonNode树</span></div>
<pre class="crayon-plain-tag">ObjectMapper mapper = new ObjectMapper();
mapper.configure( JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true )

JsonNode node = mapper.readTree( "{ addresses: [ { zip: 223442 } ] }" );
Iterator&lt;String&gt; fieldNames = node.fieldNames();
while ( fieldNames.hasNext() ) {
    String fieldName = fieldNames.next();
    System.out.println( fieldName );
    JsonNode el = node.get( fieldName );
    if ( el instanceof ArrayNode ) {
        ArrayNode ael = (ArrayNode) el;
        ael.forEach( n -&gt; {
            System.out.println( n );
        } );
    }
}</pre>
<div class="blog_h3"><span class="graybg">解析为Java对象（绑定） </span></div>
<pre class="crayon-plain-tag">ObjectMapper mapper = new ObjectMapper();
// 缩进（漂亮输出pretty-printing
mapper.enable(SerializationFeature.INDENT_OUTPUT);
// 禁止把日期类型串行化为数字时间戳
mapper.disable( SerializationFeature.WRITE_DATES_AS_TIMESTAMPS );
// 遇到里面没有任何可访问字段/属性的对象时怎么办，禁用后将这种对象串行化为{}
mapper.disable( SerializationFeature.FAIL_ON_EMPTY_BEANS );
// 遇到不可映射的属性时，是否报错
mapper.disable( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES );
// 允许把空串绑定到null值
mapper.enable( DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT );
// 允许非标准的JSON格式：使用单引号
mapper.configure( JsonParser.Feature.ALLOW_SINGLE_QUOTES, true );
// 允许非标准的JSON格式：不带引号的字段名
mapper.configure( JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true );
// 允许JSON中的C/C++风格的注释
mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
// 启用非ASCI字符（默认启用）
mapper.configure( JsonGenerator.Feature.ESCAPE_NON_ASCII, false );

// 绑定为特定类型
Entity entity = mapper.readValue(json, Entity.class);
// 默认自动转换为Map或者List之类集合对象
Map entity = mapper.readValue(json);</pre>
<div class="blog_h2"><span class="graybg">类型转换</span></div>
<p>Jackson有时可以用来进行数据类型的转换，例如：</p>
<pre class="crayon-plain-tag">// 在包装类型和基本类型的集合之间进行转换
List&lt;Integer&gt; sourceList = ...;
int[] ints = mapper.convertValue(sourceList, int[].class);
// 在POJO和Map之间进行转换
Map&lt;String,Object&gt; propertyMap = mapper.convertValue(pojoValue, Map.class);
PojoType pojo = mapper.convertValue(propertyMap, PojoType.class);
// 将Base64转换为字节数组
String base64 = "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz";
byte[] binary = mapper.convertValue(base64, byte[].class);</pre>
<div class="blog_h2"><span class="graybg">数据绑定</span></div>
<p>JSON到Java对象的数据绑定，主要依赖于注解</p>
<div class="blog_h3"><span class="graybg">注解列表</span></div>
<table class="full-width fixed-word-wrap">
<thead>
<tr>
<td style="width: 20%; text-align: center;">注解</td>
<td style="text-align: center;">说明</td>
</tr>
</thead>
<tbody>
<tr>
<td>@JsonProperty</td>
<td>
<p>用于字段/setter/getter上，指定该字段映射到的JSON字段名</p>
<p>属性：<br />defaultValue  指定默认值，核心绑定模块没有使用该属性</p>
</td>
</tr>
<tr>
<td>@JsonIgnore</td>
<td>用于字段/setter上，指定该字段不进行数据绑定</td>
</tr>
<tr>
<td>@JsonIgnoreType</td>
<td>用于类上，指定哪些类型的字段都被忽略</td>
</tr>
<tr>
<td>@JsonAutoDetect</td>
<td>用于类上，指定哪些类型的方法用于属性的自动发现。示例：<br />
<pre class="crayon-plain-tag">@JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class PrivateBean {
    private int id;
    private String name;
}</pre>
</td>
</tr>
<tr>
<td>@JsonIgnoreProperties</td>
<td>用于类上，指定哪些字段不进行数据绑定</td>
</tr>
<tr>
<td>@JsonInclude</td>
<td>用于类或字段上，指定哪些“无值“（null、空）需要包含在串行化过程中</td>
</tr>
<tr>
<td>@JsonFormat</td>
<td>指定如何格式化某个字段，例如：<br />
<pre class="crayon-plain-tag">// 格式化为带毫秒的
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ", locale = "zh", timezone = "GMT+8")
// 格式化为数字时间戳
@JsonFormat(shape = JsonFormat.Shape.NUMBER)
private Date date;</pre>
</td>
</tr>
<tr>
<td>@JsonUnwrapped</td>
<td>在串行化时，展开一个嵌入式对象，在反串行化时，包装对应的几个字段为对象</td>
</tr>
<tr>
<td>@JsonView</td>
<td>用于定义视图，每个POJO可以定义多个视图，这些视图包含不同的属性</td>
</tr>
<tr>
<td>@JsonNaming</td>
<td>
<p>用于指定JSON与POJO转换时的名称映射策略：<br />LOWER_CAMEL_CASE  JSON使用小写开头的驼峰式<br />KEBAB_CASE  JSON使用短横线连接式，例如kebab-case<br />SNAKE_CASE  JSON使用下划线连接时，snake_case<br />UPPER_CAMEL_CASE  JSON使用大写开头的驼峰式，UpperCamelCase</p>
<p>示例：</p>
<pre class="crayon-plain-tag">@JsonNaming( PropertyNamingStrategy.SnakeCaseStrategy.class )
public class FaceRecogResult {} </pre>
</td>
</tr>
<tr>
<td colspan="2"><strong><em>反串行化注解</em></strong></td>
</tr>
<tr>
<td>@JacksonInject</td>
<td>
<p>指示属性通过注入得到，而不是从JSON解析到
<p>示例：</p>
<pre class="crayon-plain-tag">public class BeanWithInject {
    @JacksonInject
    public int key;
}

// 注入的上下文对象
InjectableValues inject = new InjectableValues.Std()
                .addValue( int.class, 1 ).addValue( "key", "value" );
new ObjectMapper().reader(inject).forType(BeanWithInject.class).readValue(json);</pre>
</td>
</tr>
<tr>
<td>@JsonAnySetter</td>
<td>定义一个具有两个参数的方法为通配的Setter，用于绑定未成功映射的JSON属性</td>
</tr>
<tr>
<td>@JsonCreator</td>
<td>Jackson JSON不需要默认构造器。在公共/私有的构造器上加上此注解，则Jackson在绑定时自动调用此构造器来创建对象：<br />
<pre class="crayon-plain-tag">@JsonCreator
private CtorBean(@JsonProperty("name") String name, @JsonProperty("age") int age)
{
    this.name = name;
    this.age = age;
}</pre>
<p>或者，你也可以注解在静态的工厂方法上：</p>
<pre class="crayon-plain-tag">@JsonCreator
public static FactoryBean create(@JsonProperty("name") String name) {
    // construct and return an instance
} </pre>
</td>
</tr>
<tr>
<td><span style="color: #24292e;">@JsonSetter</span></td>
<td>用于指定任意方法为Setter</td>
</tr>
<tr>
<td><span style="color: #24292e;">@JsonEnumDefaultValue</span></td>
<td>2.8新增。反串行化未知枚举值时，给出默认值</td>
</tr>
<tr>
<td><span style="color: #24292e;">@JsonDeserialize</span></td>
<td>指定一个自定义的反串行化器：<br />
<pre class="crayon-plain-tag">public class Event {
    @JsonDeserialize(using = CustomDateDeserializer.class)
    public Date eventDate;
}</pre>
</td>
</tr>
<tr>
<td colspan="2"><strong><em>串行化注解</em></strong></td>
</tr>
<tr>
<td><span style="color: #24292e;">@JsonAnyGetter</span></td>
<td>指定一个用作通配Getter的方法，调用该方法应该获得一个Map，其中所有键会作为JSON的额外属性</td>
</tr>
<tr>
<td><span style="color: #24292e;">@JsonGetter</span></td>
<td>用于指定任意方法为Getter</td>
</tr>
<tr>
<td>@JsonPropertyOrder</td>
<td>用于指定属性的串行化顺序</td>
</tr>
<tr>
<td>@JsonRawValue</td>
<td>
<p>指示一个属性的值应该原样的放置到产生的JSON中，不进行任何转义
<p>在属性值是预先准备好的JSON格式时，使用该注解</p>
</td>
</tr>
<tr>
<td>@JsonValue</td>
<td>在POJO的某个方法上标注，当此POJO被串行化时，调用此方法得到的值作为串行化结果 </td>
</tr>
<tr>
<td>@JsonRootName </td>
<td>给串行化后的POJO加上一个外套：<br />
<pre class="crayon-plain-tag">@JsonRootName(value = "user")
public class UserWithRoot {
    public int id;
    public String name;
}</pre></p>
<p>导致串行化为：</p>
<pre class="crayon-plain-tag">{
    "user": {
        "id": 1,
        "name": "John"
    }
}</pre>
</td>
</tr>
<tr>
<td>@JsonAppend</td>
<td>在串行化时添加额外字段，而不需要改变类。示例：<br />
<pre class="crayon-plain-tag">@JsonAppend(attrs = { 
  @JsonAppend.Attr(value = "version") 
})
public class BeanWithAppend {
    private int id;
    private String name;
}
ObjectWriter writer = mapper.writerFor(BeanWithAppend.class).withAttribute("version", "1.0");
System.out.println( writer.writeValueAsString(bean) );
// 输出如下：
{
    "id": 2,
    "name": "Bean With Append Annotation",
    "version": "1.0"
}</pre>
</td>
</tr>
<tr>
<td>@JsonSerialize</td>
<td>指定一个自定义的串行化器：<br />
<pre class="crayon-plain-tag">public class Event {
    @JsonSerialize(using = CustomDateSerializer.class)
    public Date eventDate;
}</pre>
</td>
</tr>
<tr>
<td colspan="2"><strong><em>类型处理</em></strong></td>
</tr>
<tr>
<td>@JsonSubTypes</td>
<td>
<p>用于类上，指示该类型的子类型，反串行化多态类时如果基于逻辑类型名称，则可以使用
<p>示例一：</p>
<pre class="crayon-plain-tag">@JsonTypeInfo( 
    use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class" 
)
@JsonSubTypes( {
        @JsonSubTypes.Type( value = Lion.class, name = "lion" ),
        @JsonSubTypes.Type( value = Elephant.class, name = "elephant" )
} )
abstract class Animal {}
class Lion extends Animal {}
class Elephant extends Animal {}</pre>
<p> 串行化结果为：</p>
<pre class="crayon-plain-tag">// mapper.writeValue( System.out, new Lion() );
{
  "@class" : "cc.gmem.study.jackson.Lion"
}</pre>
<p> 示例二：</p>
<pre class="crayon-plain-tag">@JsonTypeInfo( 
    use = JsonTypeInfo.Id.MINIMAL_CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class" 
)
abstract class Animal {}</pre>
<p> 串行化结果为：</p>
<pre class="crayon-plain-tag">{
  "@class" : ".Lion"
}</pre>
<p>类似的：</p>
<pre class="crayon-plain-tag">@JsonTypeInfo( use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class" )
// 串行化结果：
{
  "@class" : "com.kingsmartsi.pems.fr.stport.vo.Lion"
}

@JsonTypeInfo( use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="@class" )
abstract class Animal {}
// 串行化结果：
{
  "@class" : "Lion"
} </pre>
</td>
</tr>
<tr>
<td>@JsonTypeId</td>
<td>用于类上，指示该字段的值用作类型标识</td>
</tr>
<tr>
<td>@JsonTypeName</td>
<td>用于类上，定义一个逻辑类名。示例：<br />
<pre class="crayon-plain-tag">@JsonTypeInfo( use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, property="@class" )
abstract class Animal {}
@JsonTypeName("LION")
class Lion extends Animal {}

// 串行化结果：
{
  "@class" : "LION"
}</pre>
</td>
</tr>
<tr>
<td colspan="2"><strong><em>对象引用和标识符</em></strong></td>
</tr>
<tr>
<td>
<p>@JsonManagedReference
<p>@JsonBackReference</p>
</td>
<td>
<p>这一对注解用于指示、处理父子关系。可以用来处理对象循环引用</p>
<p>示例：</p>
<pre class="crayon-plain-tag">class Hotel {
    // 管理方，负责输出JSON
    @JsonManagedReference
    private List&lt;Room&gt; rooms;
}
class Room {
    // 被管理方，属性被忽略
    @JsonBackReference
    private Hotel hotel;
}

// mapper.writeValue( System.out, hotel );
{
  "rooms" : [ { }, { } ]
} </pre>
</td>
</tr>
<tr>
<td>@JsonIdentityInfo</td>
<td>
<p>类/属性注解，用于指定对象标识符，这样，指向单个POJO的多个引用可以被正确的反串行化。可以用于处理对象循环引用
<p>示例：</p>
<pre class="crayon-plain-tag">@JsonIdentityInfo(
        generator = ObjectIdGenerators.PropertyGenerator.class,
        property = "id"
)
class Hotel {
    private int id;
    private List&lt;Room&gt; rooms;
}
@JsonIdentityInfo(
        generator = ObjectIdGenerators.PropertyGenerator.class,
        property = "id"
)
class Room {
    private int id;
    private Hotel hotel;
}

// 串行化Hotel的结果为：
{
  "id" : 1,
  "rooms" : [ {
    "id" : 100,
    "hotel" : 1
  }, {
    "id" : 101,
    "hotel" : 1
  } ]
} </pre>
</td>
</tr>
</tbody>
</table>
<div class="blog_h1"><span class="graybg">常见问题</span></div>
<div class="blog_h3"><span class="graybg">JacksonJson把JSON绑定为对象出错</span></div>
<p>报错信息：Unrecognized field "***" (Class ***), not marked as ignorable<br /> 报错原因：JSON中包含对象没有的属性<br /> 解决办法：
<pre class="crayon-plain-tag">#方法一
@Entity
@Table ( name = "T_USER" )
@JsonIgnoreProperties ( ignoreUnknown = true )
public class User implements java.io.Serializable

#方法二
ObjectMapper objectMapper = getObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);</pre>
<div>
<div class="blog_h3"><span class="graybg">JacksonJson把对象转换为JSON，导致StackOvewFlowError</span></div>
</div>
<p>报错信息：存在循环引用<br /> 解决办法：设置@JsonIgnore。JacksonJson 2.x版本中有专门处理循环引用的注解</p>
</div><p>The post <a rel="nofollow" href="https://blog.gmem.cc/jacksonjson-faq">JacksonJson知识集锦</a> appeared first on <a rel="nofollow" href="https://blog.gmem.cc">绿色记忆</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.gmem.cc/jacksonjson-faq/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
