Skip to content

Commit

Permalink
add FieldTypeResolver support
Browse files Browse the repository at this point in the history
  • Loading branch information
wenshao committed Apr 13, 2016
1 parent b3f8bd7 commit 5c1e29b
Show file tree
Hide file tree
Showing 8 changed files with 282 additions and 222 deletions.
26 changes: 25 additions & 1 deletion src/main/java/com/alibaba/fastjson/parser/DefaultJSONParser.java
Expand Up @@ -60,6 +60,7 @@
import com.alibaba.fastjson.parser.deserializer.ExtraProcessor; import com.alibaba.fastjson.parser.deserializer.ExtraProcessor;
import com.alibaba.fastjson.parser.deserializer.ExtraTypeProvider; import com.alibaba.fastjson.parser.deserializer.ExtraTypeProvider;
import com.alibaba.fastjson.parser.deserializer.FieldDeserializer; import com.alibaba.fastjson.parser.deserializer.FieldDeserializer;
import com.alibaba.fastjson.parser.deserializer.FieldTypeResolver;
import com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer; import com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import com.alibaba.fastjson.parser.deserializer.ResolveFieldDeserializer; import com.alibaba.fastjson.parser.deserializer.ResolveFieldDeserializer;
Expand Down Expand Up @@ -99,6 +100,7 @@ public class DefaultJSONParser implements Closeable {


private List<ExtraTypeProvider> extraTypeProviders = null; private List<ExtraTypeProvider> extraTypeProviders = null;
private List<ExtraProcessor> extraProcessors = null; private List<ExtraProcessor> extraProcessors = null;
protected FieldTypeResolver fieldTypeResolver = null;


static { static {
primitiveClasses.add(boolean.class); primitiveClasses.add(boolean.class);
Expand Down Expand Up @@ -448,7 +450,21 @@ public final Object parseObject(final Map object, Object fieldName) {
ctxLocal = setContext(context, input, key); ctxLocal = setContext(context, input, key);
} }


Object obj = this.parseObject(input, key); Object obj = null;
boolean objParsed = false;
if (fieldTypeResolver != null) {
String resolveFieldName = key != null ? key.toString() : null;
Type fieldType = fieldTypeResolver.resolve(object, resolveFieldName);
if (fieldType != null) {
ObjectDeserializer fieldDeser = config.getDeserializer(fieldType);
obj = fieldDeser.deserialze(this, fieldType, key);
objParsed = true;
}
}
if (!objParsed) {
obj = this.parseObject(input, key);
}

if (ctxLocal != null && input != obj) { if (ctxLocal != null && input != obj) {
ctxLocal.object = object; ctxLocal.object = object;
} }
Expand Down Expand Up @@ -1167,6 +1183,14 @@ public List<ExtraTypeProvider> getExtraTypeProviders() {
public List<ExtraTypeProvider> getExtraTypeProvidersDirect() { public List<ExtraTypeProvider> getExtraTypeProvidersDirect() {
return extraTypeProviders; return extraTypeProviders;
} }

public FieldTypeResolver getFieldTypeResolver() {
return fieldTypeResolver;
}

public void setFieldTypeResolver(FieldTypeResolver fieldTypeResolver) {
this.fieldTypeResolver = fieldTypeResolver;
}


public void setContext(ParseContext context) { public void setContext(ParseContext context) {
if (lexer.isEnabled(Feature.DisableCircularReferenceDetect)) { if (lexer.isEnabled(Feature.DisableCircularReferenceDetect)) {
Expand Down
18 changes: 9 additions & 9 deletions src/main/java/com/alibaba/fastjson/parser/ParserConfig.java
Expand Up @@ -77,6 +77,7 @@
import com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer; import com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer;
import com.alibaba.fastjson.parser.deserializer.JavaObjectDeserializer; import com.alibaba.fastjson.parser.deserializer.JavaObjectDeserializer;
import com.alibaba.fastjson.parser.deserializer.Jdk8DateCodec; import com.alibaba.fastjson.parser.deserializer.Jdk8DateCodec;
import com.alibaba.fastjson.parser.deserializer.MapDeserializer;
import com.alibaba.fastjson.parser.deserializer.NumberDeserializer; import com.alibaba.fastjson.parser.deserializer.NumberDeserializer;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import com.alibaba.fastjson.parser.deserializer.OptionalCodec; import com.alibaba.fastjson.parser.deserializer.OptionalCodec;
Expand All @@ -99,7 +100,6 @@
import com.alibaba.fastjson.serializer.FloatCodec; import com.alibaba.fastjson.serializer.FloatCodec;
import com.alibaba.fastjson.serializer.IntegerCodec; import com.alibaba.fastjson.serializer.IntegerCodec;
import com.alibaba.fastjson.serializer.LongCodec; import com.alibaba.fastjson.serializer.LongCodec;
import com.alibaba.fastjson.serializer.MapCodec;
import com.alibaba.fastjson.serializer.MiscCodec; import com.alibaba.fastjson.serializer.MiscCodec;
import com.alibaba.fastjson.serializer.ObjectArrayCodec; import com.alibaba.fastjson.serializer.ObjectArrayCodec;
import com.alibaba.fastjson.serializer.ReferenceCodec; import com.alibaba.fastjson.serializer.ReferenceCodec;
Expand Down Expand Up @@ -180,15 +180,15 @@ private ParserConfig(ASMDeserializerFactory asmFactory, ClassLoader parentClassL
derializers.put(java.util.Date.class, DateCodec.instance); derializers.put(java.util.Date.class, DateCodec.instance);
derializers.put(Calendar.class, CalendarCodec.instance); derializers.put(Calendar.class, CalendarCodec.instance);


derializers.put(JSONObject.class, MapCodec.instance); derializers.put(JSONObject.class, MapDeserializer.instance);
derializers.put(JSONArray.class, CollectionCodec.instance); derializers.put(JSONArray.class, CollectionCodec.instance);


derializers.put(Map.class, MapCodec.instance); derializers.put(Map.class, MapDeserializer.instance);
derializers.put(HashMap.class, MapCodec.instance); derializers.put(HashMap.class, MapDeserializer.instance);
derializers.put(LinkedHashMap.class, MapCodec.instance); derializers.put(LinkedHashMap.class, MapDeserializer.instance);
derializers.put(TreeMap.class, MapCodec.instance); derializers.put(TreeMap.class, MapDeserializer.instance);
derializers.put(ConcurrentMap.class, MapCodec.instance); derializers.put(ConcurrentMap.class, MapDeserializer.instance);
derializers.put(ConcurrentHashMap.class, MapCodec.instance); derializers.put(ConcurrentHashMap.class, MapDeserializer.instance);


derializers.put(Collection.class, CollectionCodec.instance); derializers.put(Collection.class, CollectionCodec.instance);
derializers.put(List.class, CollectionCodec.instance); derializers.put(List.class, CollectionCodec.instance);
Expand Down Expand Up @@ -405,7 +405,7 @@ public ObjectDeserializer getDeserializer(Class<?> clazz, Type type) {
} else if (Collection.class.isAssignableFrom(clazz)) { } else if (Collection.class.isAssignableFrom(clazz)) {
derializer = CollectionCodec.instance; derializer = CollectionCodec.instance;
} else if (Map.class.isAssignableFrom(clazz)) { } else if (Map.class.isAssignableFrom(clazz)) {
derializer = MapCodec.instance; derializer = MapDeserializer.instance;
} else if (Throwable.class.isAssignableFrom(clazz)) { } else if (Throwable.class.isAssignableFrom(clazz)) {
derializer = new ThrowableDeserializer(this, clazz); derializer = new ThrowableDeserializer(this, clazz);
} else { } else {
Expand Down
@@ -0,0 +1,7 @@
package com.alibaba.fastjson.parser.deserializer;

import java.lang.reflect.Type;

public interface FieldTypeResolver extends ParseProcess {
Type resolve(Object object, String fieldName);
}
207 changes: 7 additions & 200 deletions ...alibaba/fastjson/serializer/MapCodec.java → .../parser/deserializer/MapDeserializer.java 100755 → 100644
@@ -1,28 +1,11 @@
/* package com.alibaba.fastjson.parser.deserializer;
* Copyright 1999-2101 Alibaba Group.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.fastjson.serializer;

import java.io.IOException;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.HashMap; import java.util.HashMap;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.IdentityHashMap; import java.util.IdentityHashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.SortedMap; import java.util.SortedMap;
Expand All @@ -39,192 +22,15 @@
import com.alibaba.fastjson.parser.JSONLexer; import com.alibaba.fastjson.parser.JSONLexer;
import com.alibaba.fastjson.parser.JSONToken; import com.alibaba.fastjson.parser.JSONToken;
import com.alibaba.fastjson.parser.ParseContext; import com.alibaba.fastjson.parser.ParseContext;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import com.alibaba.fastjson.util.TypeUtils; import com.alibaba.fastjson.util.TypeUtils;


/** public class MapDeserializer implements ObjectDeserializer {
* @author wenshao[szujobs@hotmail.com] public static MapDeserializer instance = new MapDeserializer();
*/
public class MapCodec implements ObjectSerializer, ObjectDeserializer {

public static MapCodec instance = new MapCodec();

@SuppressWarnings({ "rawtypes"})
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType, int features) throws IOException {
SerializeWriter out = serializer.out;

if (object == null) {
out.writeNull();
return;
}

Map<?, ?> map = (Map<?, ?>) object;

// if (out.isEnabled(SerializerFeature.SortField)) {
// if ((!(map instanceof SortedMap)) && !(map instanceof LinkedHashMap)) {
// try {
// map = new TreeMap(map);
// } catch (Exception ex) {
// // skip
// }
// }
// }

if (serializer.containsReference(object)) {
serializer.writeReference(object);
return;
}

SerialContext parent = serializer.context;
serializer.setContext(parent, object, fieldName, 0);
try {
out.write('{');

serializer.incrementIndent();

Class<?> preClazz = null;
ObjectSerializer preWriter = null;

boolean first = true;

if (out.isEnabled(SerializerFeature.WriteClassName)) {
Class<?> mapClass = map.getClass();
boolean containsKey = (mapClass == JSONObject.class || mapClass == HashMap.class || mapClass == LinkedHashMap.class)
&& map.containsKey(JSON.DEFAULT_TYPE_KEY);
if (!containsKey) {
out.writeFieldName(JSON.DEFAULT_TYPE_KEY);
out.writeString(object.getClass().getName());
first = false;
}
}

for (Map.Entry entry : map.entrySet()) {
Object value = entry.getValue();

Object entryKey = entry.getKey();

{
List<PropertyPreFilter> preFilters = serializer.propertyPreFilters;
if (preFilters != null && preFilters.size() > 0) {
if (entryKey == null || entryKey instanceof String) {
if (!FilterUtils.applyName(serializer, object, (String) entryKey)) {
continue;
}
} else if (entryKey.getClass().isPrimitive() || entryKey instanceof Number) {
String strKey = JSON.toJSONString(entryKey);
if (!FilterUtils.applyName(serializer, object, strKey)) {
continue;
}
}
}
}

{
List<PropertyFilter> propertyFilters = serializer.propertyFilters;
if (propertyFilters != null && propertyFilters.size() > 0) {
if (entryKey == null || entryKey instanceof String) {
if (!FilterUtils.apply(serializer, object, (String) entryKey, value)) {
continue;
}
} else if (entryKey.getClass().isPrimitive() || entryKey instanceof Number) {
String strKey = JSON.toJSONString(entryKey);
if (!FilterUtils.apply(serializer, object, strKey, value)) {
continue;
}
}
}
}

{
List<NameFilter> nameFilters = serializer.nameFilters;
if (nameFilters != null && nameFilters.size() > 0) {
if (entryKey == null || entryKey instanceof String) {
entryKey = FilterUtils.processKey(serializer, object, (String) entryKey, value);
} else if (entryKey.getClass().isPrimitive() || entryKey instanceof Number) {
String strKey = JSON.toJSONString(entryKey);
entryKey = FilterUtils.processKey(serializer, object, strKey, value);
}
}
}

{
List<ValueFilter> valueFilters = serializer.valueFilters;
if (valueFilters != null && valueFilters.size() > 0) {
if (entryKey == null || entryKey instanceof String) {
value = FilterUtils.processValue(serializer, object, (String) entryKey, value);
} else if (entryKey.getClass().isPrimitive() || entryKey instanceof Number) {
String strKey = JSON.toJSONString(entryKey);
value = FilterUtils.processValue(serializer, object, strKey, value);
}
}
}

if (value == null) {
if (!out.isEnabled(SerializerFeature.WriteMapNullValue)) {
continue;
}
}

if (entryKey instanceof String) {
String key = (String) entryKey;

if (!first) {
out.write(',');
}

if (out.isEnabled(SerializerFeature.PrettyFormat)) {
serializer.println();
}
out.writeFieldName(key, true);
} else {
if (!first) {
out.write(',');
}

if (out.isEnabled(SerializerFeature.BrowserCompatible)
|| out.isEnabled(SerializerFeature.WriteNonStringKeyAsString)
|| out.isEnabled(SerializerFeature.BrowserSecure)) {
String strEntryKey = JSON.toJSONString(entryKey);
serializer.write(strEntryKey);
} else {
serializer.write(entryKey);
}

out.write(':');
}

first = false;

if (value == null) {
out.writeNull();
continue;
}

Class<?> clazz = value.getClass();

if (clazz == preClazz) {
preWriter.write(serializer, value, entryKey, null, 0);
} else {
preClazz = clazz;
preWriter = serializer.getObjectWriter(clazz);

preWriter.write(serializer, value, entryKey, null, 0);
}
}
} finally {
serializer.context = parent;
}

serializer.decrementIdent();
if (out.isEnabled(SerializerFeature.PrettyFormat) && map.size() > 0) {
serializer.println();
}
out.write('}');
}


@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) { public <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName) {
if (type == JSONObject.class) { if (type == JSONObject.class && parser.getFieldTypeResolver() == null) {
return (T) parser.parseObject(); return (T) parser.parseObject();
} }


Expand Down Expand Up @@ -525,6 +331,7 @@ protected Map<Object, Object> createMap(Type type) {
throw new JSONException("unsupport type " + type, e); throw new JSONException("unsupport type " + type, e);
} }
} }



public int getFastMatchToken() { public int getFastMatchToken() {
return JSONToken.LBRACE; return JSONToken.LBRACE;
Expand Down

0 comments on commit 5c1e29b

Please sign in to comment.