JSON 泛型序列化方法 与 LinkedHashMap转成对象
1、说明
本文均基于 com.alibaba.fastjson.jar 包,所以首先引入jar
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.68</version>
</dependency>
1、JSON 泛型序列化方法
**public static <T> T parseObject(String text, TypeReference<T> type, Feature... features)**
该方法可以把String parse为自己定义的实体类,前面返回值是泛型,也可以是其他jar包的数据类型,只要在后面指明它的类型就好了。
2.1 JSON 源码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.alibaba.fastjson;
import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.JSONLexer;
import com.alibaba.fastjson.parser.JSONScanner;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.parser.deserializer.ExtraProcessor;
import com.alibaba.fastjson.parser.deserializer.ExtraTypeProvider;
import com.alibaba.fastjson.parser.deserializer.FieldTypeResolver;
import com.alibaba.fastjson.parser.deserializer.ParseProcess;
import com.alibaba.fastjson.serializer.JSONSerializable;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.alibaba.fastjson.serializer.JavaBeanSerializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializeFilter;
import com.alibaba.fastjson.serializer.SerializeWriter;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.util.IOUtils;
import com.alibaba.fastjson.util.TypeUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
import java.lang.reflect.Array;
import java.lang.reflect.Type;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
public abstract class JSON implements JSONStreamAware, JSONAware {
public static TimeZone defaultTimeZone = TimeZone.getDefault();
public static Locale defaultLocale = Locale.getDefault();
public static String DEFAULT_TYPE_KEY = "@type";
static final SerializeFilter[] emptyFilters = new SerializeFilter[0];
public static String DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static int DEFAULT_PARSER_FEATURE;
public static int DEFAULT_GENERATE_FEATURE;
private static final ConcurrentHashMap<Type, Type> mixInsMapper = new ConcurrentHashMap(16);
private static final ThreadLocal<byte[]> bytesLocal;
private static final ThreadLocal<char[]> charsLocal;
public static final String VERSION = "1.2.68";
public JSON() {
}
// 省略代码 ……
/**
* <pre>
* String jsonStr = "[{\"id\":1001,\"name\":\"Jobs\"}]";
* List<Model> models = JSON.parseObject(jsonStr, new TypeReference<List<Model>>() {});
* </pre>
* @param text json string
* @param type type refernce
* @param features
* @return
*/
public static <T> T parseObject(String text, TypeReference<T> type, Feature... features) {
return parseObject(text, type.type, ParserConfig.global, DEFAULT_PARSER_FEATURE, features);
}
public static <T> T parseObject(String input, Type clazz, ParserConfig config, int featureValues,
Feature... features) {
return parseObject(input, clazz, config, null, featureValues, features);
}
@SuppressWarnings("unchecked")
public static <T> T parseObject(String input, Type clazz, ParserConfig config, ParseProcess processor,
int featureValues, Feature... features) {
if (input == null || input.isEmpty()) {
return null;
}
if (features != null) {
for (Feature feature : features) {
featureValues |= feature.mask;
}
}
DefaultJSONParser parser = new DefaultJSONParser(input, config, featureValues);
if (processor != null) {
if (processor instanceof ExtraTypeProvider) {
parser.getExtraTypeProviders().add((ExtraTypeProvider) processor);
}
if (processor instanceof ExtraProcessor) {
parser.getExtraProcessors().add((ExtraProcessor) processor);
}
if (processor instanceof FieldTypeResolver) {
parser.setFieldTypeResolver((FieldTypeResolver) processor);
}
}
T value = (T) parser.parseObject(clazz, null);
parser.handleResovleTask(value);
parser.close();
return (T) value;
}
// 省略代码 ……
}
2.2 示例
package com.icao.json;
import java.io.Serializable;
/**
* @ClassName: Person
* @Description:
* @author:
* @Date:2020/6/3 17:32
**/
public class Person implements Serializable {
private Integer id;
private String name;
private String addr;
private Integer[] child;
public Integer[] getChild() {
return child;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public String getAddr() {
return addr;
}
public void setChild(Integer[] child) {
this.child = child;
}
public void setId(Integer id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setAddr(String addr) {
this.addr = addr;
}
}
package com.icao.json;
/**
* @ClassName: PageResponse
* @Description:
* @author:
* @Date:2020/6/3 17:34
**/
public class PageResponse<T> {
private Integer pageSize;
private Integer pageNo;
private Integer count;
private T result;
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public void setPageNo(Integer pageNo) {
this.pageNo = pageNo;
}
public void setCount(Integer count) {
this.count = count;
}
public void setResult(T result) {
this.result = result;
}
public Integer getPageSize() {
return pageSize;
}
public Integer getPageNo() {
return pageNo;
}
public Integer getCount() {
return count;
}
public T getResult() {
return result;
}
}
package com.icao.json;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import java.util.List;
/**
* @ClassName: JsonTest
* @Description:
* @author:
* @Date:2020/6/3 17:32
**/
public class JsonTest {
public static void main(String[] args) {
String result = "{\"result\":[{\\\"id\\\":1,,\\\"name\\\":\\\"程成\\\",\\\"addr\\\":\\\"湖北省武汉市\\\",\\\"child\\\":[12,13]},{\\\"id\\\":2,,\\\"name\\\":\\\"武威\\\",\\\"addr\\\":\\\"湖北省宜昌市\\\",\\\"child\\\":[17,18]}],\"count\":2,\"pageSize\":50,\"pageNo\":1}";
// JSON.parseObject 对json 字符串要求很严格,需要反转义。
result = result.replace("\\\"","\"");
PageResponse<List<Person>> pageResponse = JSON.parseObject(result, new TypeReference<PageResponse<List<Person>>>() {});
System.out.println("pageResponse = "+JSON.toJSONString(pageResponse));
}
}
运行结果:
Connected to the target VM, address: '127.0.0.1:51893', transport: 'socket'
pageResponse = {"count":2,"pageNo":1,"pageSize":50,"result":[{"addr":"湖北省武汉市","child":[12,13],"id":1,"name":"程成"},{"addr":"湖北省宜昌市","child":[17,18],"id":2,"name":"武威"}]}
Disconnected from the target VM, address: '127.0.0.1:51893', transport: 'socket'
Process finished with exit code 0
2.3 忽略反转义报错
package com.icao.json;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import java.util.List;
/**
* @ClassName: JsonTest
* @Description:
* @author:
* @Date:2020/6/3 17:32
**/
public class JsonTest {
public static void main(String[] args) {
String result = "{\"result\":[{\\\"id\\\":1,,\\\"name\\\":\\\"程成\\\",\\\"addr\\\":\\\"湖北省武汉市\\\",\\\"child\\\":[12,13]},{\\\"id\\\":2,,\\\"name\\\":\\\"武威\\\",\\\"addr\\\":\\\"湖北省宜昌市\\\",\\\"child\\\":[17,18]}],\"count\":2,\"pageSize\":50,\"pageNo\":1}";
// JSON.parseObject 对json 字符串要求很严格,需要分转义。
//result = result.replace("\\\"","\"");
PageResponse<List<Person>> pageResponse = JSON.parseObject(result, new TypeReference<PageResponse<List<Person>>>() {});
System.out.println("pageResponse = "+JSON.toJSONString(pageResponse));
}
}
运行结果:
Exception in thread "main" com.alibaba.fastjson.JSONException: illegal identifier : \pos 12, line 1, column 13{"result":[{\"id\":1,,\"name\":\"程成\",\"addr\":\"湖北省武汉市\",\"child\":[12,13]},{\"id\":2,,\"name\":\"武威\",\"addr\":\"湖北省宜昌市\",\"child\":[17,18]}],"count":2,"pageSize":50,"pageNo":1}
at com.alibaba.fastjson.parser.JSONLexerBase.scanSymbolUnQuoted(JSONLexerBase.java:831)
at com.alibaba.fastjson.parser.JSONLexerBase.scanSymbol(JSONLexerBase.java:632)
at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:706)
at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.parseRest(JavaBeanDeserializer.java:1573)
at com.alibaba.fastjson.parser.deserializer.FastjsonASMDeserializer_1_Person.deserialze(Unknown Source)
at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:284)
at com.alibaba.fastjson.parser.deserializer.ArrayListTypeFieldDeserializer.parseArray(ArrayListTypeFieldDeserializer.java:181)
at com.alibaba.fastjson.parser.deserializer.ArrayListTypeFieldDeserializer.parseField(ArrayListTypeFieldDeserializer.java:69)
at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:838)
at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.deserialze(JavaBeanDeserializer.java:288)
at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:686)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:396)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:364)
at com.alibaba.fastjson.JSON.parseObject(JSON.java:278)
at com.icao.json.JsonTest.main(JsonTest.java:22)
Process finished with exit code 1
3、LinkedHashMap 转成对象 convertValue() 方法
Java中使用Jackson反序列时,部分场景下会转成LinkedHashMap,此时需要将LinkedHashMap转成对象(将任何Object类型转成实体)
一般来讲Jackson已经满足了大部分的序列化和反序列化工作,但是对于复杂的泛型实体估计未必能如愿的正常反序列,而此时对于一些泛型里面的实体对象就会反序列化成LinkedHashMap类型的。
同样,这个类型不能直接强制转换成想要的实体,此时要解决此类问题的思路如下两种:
1、继续将这个LinkedHashMap进行序列化程JSON,然后再反序列化,这样效率较低。
2、使用com.fasterxml.jackson.databind.ObjectMapper 类的 convertValue 方法将这个LinkedHashMap以Object类型转成想要的实体。
ObjectMapper objectMapper = new ObjectMapper();
Person person = objectMapper.convertValue(singleObject, Person.class);
// or:
List<Person> persons =
objectMapper.convertValue(listOfObjects, new TypeReference<List<Person>>() {});
以及
.