两个特性的作用
Jackson在反序列化是有两个可配置的特性:INTERN_FIELD_NAMES和CANONICALIZE_FIELD_NAMES。
/**
* Feature that determines whether JSON object field names are
* to be canonicalized using {@link String#intern} or not:
* if enabled, all field names will be intern()ed (and caller
* can count on this being true for all such names); if disabled,
* no intern()ing is done. There may still be basic
* canonicalization (that is, same String will be used to represent
* all identical object property names for a single document).
*<p>
* Note: this setting only has effect if
* {@link #CANONICALIZE_FIELD_NAMES} is true -- otherwise no
* canonicalization of any sort is done.
*<p>
* This setting is enabled by default.
*/
INTERN_FIELD_NAMES(true),
/**
* Feature that determines whether JSON object field names are
* to be canonicalized (details of how canonicalization is done
* then further specified by
* {@link #INTERN_FIELD_NAMES}).
*<p>
* This setting is enabled by default.
*/
CANONICALIZE_FIELD_NAMES(true)
根据注释可以看出来,这两个特性的作用是决定是否要规范化json串的key(即调用key的intern方法),并且只有在CANONICALIZE_FIELD_NAMES生效时,INTERN_FIELD_NAMES才会生效。
那么,这个两个特性是如何起作用的呢?
在获取json串的下一个token时,即ReaderBasedJsonParser的nextToken()方法中,解析了key的名称,代码如下:
boolean inObject = _parsingContext.inObject();
if (inObject) {
// First, field name itself:
String name = _parseName(i);//解析key的名称
_parsingContext.setCurrentName(name);
_currToken = JsonToken.FIELD_NAME;
i = _skipWS();
if (i != INT_COLON) {
_reportUnexpectedChar(i, "was expecting a colon to separate field name and value");
}
i = _skipWS();
}
在跟到_parseName( int i )中,可以发现这个方法调用了 _parseName2( int startPtr, int hash, int endChar), 方法_parseName2方法返回的是
_symbols.findSymbol(buf, start, len, hash),看一下findSymbol的实现会先后看到下面两个实现逻辑逻辑1:
逻辑2:if (!_canonicalize) { // [JACKSON-259] return new String(buffer, start, len); }
String newSymbol = new String(buffer, start, len); if (_intern) { newSymbol = InternCache.instance.intern(newSymbol); }
逻辑1中,如果没有配置CANONICALIZE_FIELD_NAMES,直接返回了key的名字,逻辑2中,如果配置了INTERN_FIELD_NAMES,调用intern方法。_symbols及两个字段_canonicalize和_intern是怎么初始化的
在ObjectMapper的readValue(String content, Class<T> valueType)方法中,先初始化了jsonParser(在JsonFactory的createParser方法中),protected JsonParser _createParser(Reader r, IOContext ctxt) throws IOException, JsonParseException { return new ReaderBasedJsonParser(ctxt, _parserFeatures, r, _objectCodec, _rootCharSymbols.makeChild(isEnabled(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES), isEnabled(JsonFactory.Feature.INTERN_FIELD_NAMES))); }
构造ReaderBasedJsonParser的第三个参数是,完成了_symbols及两个字段的初始化。InternCache是什么
它实现了ConcurrentHashMap,为的是防止多次调用同一个字符串的intern方法。