/** * 该特性允许parser可以识别"Not-a-Number" (NaN)标识集合作为一个合法的浮点数。 例如: allows (tokens are quoted contents, not including * quotes): * <ul> * <li>"INF" (for positive infinity), as well as alias of "Infinity" * <li>"-INF" (for negative infinity), alias "-Infinity" * <li>"NaN" (for other not-a-numbers, like result of division by zero) * </ul> */
/** * Method that calculates bit set (flags) of all features that are enabled by default. */ publicstaticintcollectDefaults(){ int flags = 0; for (Feature f : values()) { if (f.enabledByDefault()) { flags |= f.getMask(); } } return flags; }
/** * Enumeration that defines togglable features that guide the serialization feature. */ publicenumFeatureimplementsMapperConfig.ConfigFeature{ /* * /****************************************************** Introspection features * /****************************************************** */
/** * 该特性决定当遇到JSON null的对象是java 原始类型,则是否抛出异常。当false时,则使用0 for 'int', 0.0 for double 来设定原始对象初始值。 * * 默认情况下,允许原始类型可以使用null。 * * @since 1.7 */ FAIL_ON_NULL_FOR_PRIMITIVES(false),
/** * 该特性决定JSON 整数是否是一个有效的值,当被用来反序列化Java枚举值。如果false,数字可以接受,并且映射为枚举的值ordinal(); * 如果true,则数字不允许并且抛出JsonMappingException异常。后面一种行为原因是因为大部分情况下,枚举被反序列化为 JSON 字符串, 从而造成从整形到枚举的意外映射关系。 * * Feature is disabled by default (to be consistent with behavior of Jackson 1.6), i.e. to allow use of JSON * integers for Java enums. * * @since 1.7 */ FAIL_ON_NUMBERS_FOR_ENUMS(false),
/* * /****************************************************** Structural conversion features * /****************************************************** 数据结构转换特性 */
/** * 该特性决定是否接受强制非数组(JSON)值到Java集合类型。如果允许,集合反序列化将尝试处理非数组值。 * * Feature that determines whether it is acceptable to coerce non-array (in JSON) values to work with Java * collection (arrays, java.util.Collection) types. If enabled, collection deserializers will try to handle * non-array values as if they had "implicit" surrounding JSON array. This feature is meant to be used for * compatibility/interoperability reasons, to work with packages (such as XML-to-JSON converters) that leave out * JSON array in cases where there is just a single element in array. * * @since 1.8 */ ACCEPT_SINGLE_VALUE_AS_ARRAY(false),
/* * /****************************************************** Value conversion features * /****************************************************** 值转换特性 */
/** * 是否对属性使用排序,默认排序按照字母顺序。 */ SORT_PROPERTIES_ALPHABETICALLY(false), /* /****************************************************** /* Error handling features /****************************************************** */ /** * 是否允许一个类型没有注解表明打算被序列化。默认true,抛出一个异常;否则序列化一个空对象,比如没有任何属性。 * * Note that empty types that this feature has only effect on * those "empty" beans that do not have any recognized annotations * (like <code>@JsonSerialize</code>): ones that do have annotations * do not result in an exception being thrown. * * @since 1.4 */ FAIL_ON_EMPTY_BEANS(true),
/** * 封装所有异常 */ WRAP_EXCEPTIONS(true),
/* /****************************************************** /* Output life cycle features /****************************************************** */ /** * 该特性决定序列化root级对象的实现closeable接口的close方法是否在序列化后被调用。 * * 注意:如果true,则完成序列化后就关闭;如果,你可以在处理最后,调用排序操作等,则为false。 * */ CLOSE_CLOSEABLE(false),
/** * 该特性决定是否在writeValue()方法之后就调用JsonGenerator.flush()方法。 * 当我们需要先压缩,然后再flush,则可能需要false。 * */ FLUSH_AFTER_WRITE_VALUE(true), /* /****************************************************** /* Data type - specific serialization configuration /****************************************************** */
/** * 决定容器空的属性(声明为Collection或者array的值)是否被序列化为空的JSON数组(true),否则强制输出。 * * Note that this does not change behavior of {@link java.util.Map}s, or * "Collection-like" types. * * @since 1.9 */ WRITE_EMPTY_JSON_ARRAYS(true) ;
public JavaType constructType(Type type){ return _constructType(type, null); } /** * Factory method that can be used if type information is passed * as Java typing returned from <code>getGenericXxx</code> methods * (usually for a return or argument type). */ public JavaType _constructType(Type type, TypeBindings context) { JavaType resultType;
// simple class? if (type instanceof Class<?>) { Class<?> cls = (Class<?>) type; /* 24-Mar-2010, tatu: Better create context if one was not passed; * mostly matters for root serialization types */ if (context == null) { context = new TypeBindings(this, cls); } resultType = _fromClass(cls, context); } // But if not, need to start resolving. elseif (type instanceof ParameterizedType) {//带有参数化的类型,比如Collection<String> resultType = _fromParamType((ParameterizedType) type, context); } elseif (type instanceof GenericArrayType) {//表示一个数组类型,成员有参数化类型或者type变量 resultType = _fromArrayType((GenericArrayType) type, context); } elseif (type instanceof TypeVariable<?>) {//其他类型的父接口 resultType = _fromVariable((TypeVariable<?>) type, context); } elseif (type instanceof WildcardType) {//通配符类型,比如? 或者 ? extends Number resultType = _fromWildcard((WildcardType) type, context); } else { // 最后类型都不符合,就会抛出非法参数异常Unrecognized Type thrownew IllegalArgumentException("Unrecognized Type: "+type.toString()); } /* * 目前只会被 simple types调用 (i.e. not for arrays, map or collections). */ if (_modifiers != null && !resultType.isContainerType()) { for (TypeModifier mod : _modifiers) { resultType = mod.modifyType(resultType, type, context, this); } } return resultType; }
protected JsonToken _initForReading(JsonParser jp) throws IOException, JsonParseException, JsonMappingException { /* 首先:必须只想一个token;没有token的情况只可以出现在第一次,和当前token被清除。 * 此外,这里的JsonParser具体是指ReaderBaseParser实例,(还记得把String Reader处理吗?!) */ JsonToken t = jp.getCurrentToken(); //内部使用了简单地缓存ConcurrentHashMap实现 if (t == null) { // and then we must get something... t = jp.nextToken(); // 判断当前是什么类型的JSON标识,比如对象JSON刚开始为"START_OBJECT" if (t == null) { /* [JACKSON-99] Should throw EOFException, closest thing * semantically */ thrownew EOFException("No content to map to Object due to end of input"); } } return t; }
/** * Method called to locate deserializer for the passed root-level value. */ protected JsonDeserializer<Object> _findRootDeserializer(DeserializationConfig cfg, JavaType valueType) throws JsonMappingException { // First: have we already seen it? JsonDeserializer<Object> deser = _rootDeserializers.get(valueType);//从缓存中获取对应类型的反序列化实例 if (deser != null) { return deser; } // Nope: need to ask provider to resolve it deser = _deserializerProvider.findTypedValueDeserializer(cfg, valueType, null);//使用StdDeserializationContext默认的DeserializationContext实现。反序列化类实际上就是对某一类型进行详细描述,如下图。 if (deser == null) { // can this happen? thrownew JsonMappingException("Can not find a deserializer for type "+valueType); } _rootDeserializers.put(valueType, deser);//放入缓存中 return deser; }
publicfinal Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { JsonToken t = jp.getCurrentToken(); // common case first: if (t == JsonToken.START_OBJECT) { jp.nextToken(); return deserializeFromObject(jp, ctxt); } // and then others, generally requiring use of @JsonCreator switch (t) { case VALUE_STRING: return deserializeFromString(jp, ctxt); case VALUE_NUMBER_INT: return deserializeFromNumber(jp, ctxt); case VALUE_NUMBER_FLOAT: return deserializeFromDouble(jp, ctxt); case VALUE_EMBEDDED_OBJECT: return jp.getEmbeddedObject(); case VALUE_TRUE: case VALUE_FALSE: return deserializeFromBoolean(jp, ctxt); case START_ARRAY: // these only work if there's a (delegating) creator... return deserializeFromArray(jp, ctxt); case FIELD_NAME: case END_OBJECT: // added to resolve [JACKSON-319], possible related issues return deserializeFromObject(jp, ctxt); } throw ctxt.mappingException(getBeanClass()); }
// BeanPropertyMap类是一个存储属性名到SettableBeanProperty实例之间的映射的工具类。该类主要代替HashMap,做了一些业务优化。 public SettableBeanProperty find(String key) { int index = key.hashCode() & _hashMask;//hash找到bucket位置 Bucket bucket = _buckets[index];// // Let's unroll first lookup since that is null or match in 90+% cases if (bucket == null) {//如果不存在,则返回null returnnull; } // Primarily we do just identity comparison as keys should be interned if (bucket.key == key) { // 当没有hash碰撞时,则会相等 return bucket.value; } while ((bucket = bucket.next) != null) {//不能直接相等,则遍历找到bucket里面所有的key if (bucket.key == key) { return bucket.value; } } // Do we need fallback for non-interned Strings? return _findWithEquals(key, index); }