欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JSON 泛型序列化方法 与 LinkedHashMap转成对象

程序员文章站 2024-02-21 12:24:40
...

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&lt;Model&gt; models = JSON.parseObject(jsonStr, new TypeReference&lt;List&lt;Model&gt;&gt;() {});
     * </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));

    }

}

 
运行结果:

JSON 泛型序列化方法 与 LinkedHashMap转成对象

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>>() {});
    

以及
JSON 泛型序列化方法 与 LinkedHashMap转成对象
JSON 泛型序列化方法 与 LinkedHashMap转成对象
 
 
 
 
 
 
 
 
 
.