MappingProvider 反序列化器

序列化和反序列化

序列化: 把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中。 核心作用是对象状态的保存与重建。 

反序列化:客户端从文件中或网络上获得序列化后的对象字节流,根据字节流中所保存的对象状态及描述信息,通过反序列化重建对象。

通俗一点:

序列化: 对象--->JSON 

反序列化: JSON ---> 对象

MappingProvider

MappinProvider是一个接口, 图中虚线箭头代表实现,下方六个是MappingProvider的实现类.

JsonPath将自动尝试将结果强制转换为调用方所期望的类型。

计算路径时需要知道路径是明确的还是不明确的,明确的返回单个值,不明确的返回一个List.

默认情况下,一个简单的对象映射器由MappingProvider SPI提供。JsonPath提供了默认的实现: JsonSmartMappingProvider。但是不能将json字符串转为POJO对象。

JsonPath提供的MappingProvider如下:

JsonSmartMappingProvider(默认)

GsonMappingProvider

JacksonMappingProvider

JakartaMappingProvider

JsonOrgMappingProvider

TapestryMappingProvider

MappingProvider内只有两个方法:

public interface MappingProvider {
    /**
     *
     * @param source object to map
     * @param targetType the type the source object should be mapped to
     * @param configuration current configuration
     * @param <T> the mapped result type
     * @return return the mapped object
     */
    <T> T map(Object source, Class<T> targetType, Configuration configuration);

    /**
     *
     * @param source object to map
     * @param targetType the type the source object should be mapped to
     * @param configuration current configuration
     * @param <T> the mapped result type
     * @return return the mapped object
     */
    <T> T map(Object source, TypeRef<T> targetType, Configuration configuration);
}

API

MappingProvider (json-path 2.2.0 API)https://www.javadoc.io/static/com.jayway.jsonpath/json-path/2.2.0/com/jayway/jsonpath/spi/mapper/MappingProvider.html

 

很容易理解, map将源对象返回指定类型.

JsonSmartMappingProvider

JsonSmartMappingProvider提供了基本数据类型的转换:

static {
        DEFAULT.registerReader(Long.class, new LongReader());
        DEFAULT.registerReader(long.class, new LongReader());
        DEFAULT.registerReader(Integer.class, new IntegerReader());
        DEFAULT.registerReader(int.class, new IntegerReader());
        DEFAULT.registerReader(Double.class, new DoubleReader());
        DEFAULT.registerReader(double.class, new DoubleReader());
        DEFAULT.registerReader(Float.class, new FloatReader());
        DEFAULT.registerReader(float.class, new FloatReader());
        DEFAULT.registerReader(BigDecimal.class, new BigDecimalReader());
        DEFAULT.registerReader(String.class, new StringReader());
        DEFAULT.registerReader(Date.class, new DateReader());
        DEFAULT.registerReader(BigInteger.class, new BigIntegerReader());
        DEFAULT.registerReader(boolean.class, new BooleanReader());
    }

方法实现:

    @Override
    public <T> T map(Object source, Class<T> targetType, Configuration configuration) {
        if(source == null){
            /*
            判断传入映射对象是否为空,空直接返回null
            */
            return null;
        }
        if (targetType.isAssignableFrom(source.getClass())) {
            /*
            确定此class对象表示的类或接口是否与指定class参数表示的类或接口相同,或为其超类或超            
            接口。如果是,它返回true;否则返回false。如果这个Class对象表示一个基元类型,如果. 
            指.定的Class参数正是这个Class对象,这个方法返回true;否则返回false。
            具体来说,此方法测试是否可以通过标识转换或通过扩展引用转换将指定Class参数表示的类. 
            型.转换为此Class对象表示的类型。
            */
            return (T) source;
        }
        try {
            /*
            如果source既不是Map映射也不是Array数组,
            直接返回. 
            */
            if(!configuration.jsonProvider().isMap(source) && !configuration.jsonProvider().isArray(source)){
                return factory.call().getMapper(targetType).convert(source);
            }
            /*
            转换为targetType类型     
            */
            String s = configuration.jsonProvider().toJson(source);
            return (T) JSONValue.parse(s, targetType);
        } catch (Exception e) {
          
            throw new MappingException(e);
        }

    }

    @Override
    public <T> T map(Object source, TypeRef<T> targetType, Configuration configuration) {
        throw new UnsupportedOperationException("Json-smart provider does not support TypeRef! Use a Jackson or Gson based provider");
    }

JsonSmartMappingProvider不支持TyprRef, JacksonMappingProvider或者GsonMappingProvider支持.

继续看JsonReader下的convert方法

一下子就和上面JsonSmartMappingProvider提供的基本数据类型的转换联系起来.

列举一个:

private static class IntegerReader extends JsonReaderI<Integer> {
        public IntegerReader() {
            super(null);
        }
        public Integer convert(Object src) {
            if(src == null){
                return null;
            }
            if(Integer.class.isAssignableFrom(src.getClass())){
               return (Integer) src;
            } else if (Long.class.isAssignableFrom(src.getClass())) {
                return ((Long) src).intValue();
            } else if (Double.class.isAssignableFrom(src.getClass())) {
                return ((Double) src).intValue();
            } else if (BigDecimal.class.isAssignableFrom(src.getClass())) {
                return ((BigDecimal) src).intValue();
            } else if (Float.class.isAssignableFrom(src.getClass())) {
                return ((Float) src).intValue();
            } else if (String.class.isAssignableFrom(src.getClass())) {
                return Integer.valueOf(src.toString());
            }
            throw new MappingException("can not map a " + src.getClass() + " to " + Integer.class.getName());
        }
    }

既然JsonSmartMappingProvider不支持TyprRef, 而JacksonMappingProvider或者GsonMappingProvider支持. 如何切换Provider呢? 实际上是可以自己切换的, 比如切换到

JacksonJsonMappingProvider:

Configuration.setDefaults(new Configuration.Defaults() {

    private final JsonProvider jsonProvider = new JacksonJsonProvider();
    private final MappingProvider mappingProvider = new JacksonMappingProvider();

    @Override
    public JsonProvider jsonProvider() {
        return jsonProvider;
    }

    @Override
    public MappingProvider mappingProvider() {
        return mappingProvider;
    }

    @Override
    public Set<Option> options() {
        return EnumSet.noneOf(Option.class);
    }
});

如果将JsonPath配置为使用JacksonMappingProvider或GsonMappingProvider,可以将JsonPath输出直接映射到POJO中。

代码:

Book 类:

public class Book{
    private String category;
    private String author;
    private String title;
    private Double price;
    private String isbn;

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public String getIsbn() {
        return isbn;
    }

    public void setIsbn(String isbn) {
        this.isbn = isbn;
    }

    @Override
    public String toString(){
        if (this.isbn != null){
            return "category : " + getCategory() + " author: " + getAuthor()
                    + " title : " + getTitle() + " price : " + getPrice() + " isbn : " + getIsbn();
        }
        return "category : " + getCategory() + " author: " + getAuthor()
                + " title : " + getTitle() + " price : " + getPrice();
    }
}

Demo:

public class JacksonMappingProviderDemo {
    public static void main(String[] args) {

        // 转化成反序列化成Date类
        String json1 = "{\"date_as_long\" : 1658908587321}";
        Date date = JsonPath.parse(json1).read("$['date_as_long']", Date.class);
        System.out.println(date);

        Configuration conf = Configuration
                .builder()
                .mappingProvider(new JacksonMappingProvider())
                .build();
        Book[] books = JsonPath.using(conf).parse(json).read("$.store.book[*]", Book[].class);
        for (Book book : books) {
            System.out.println(book.toString());
        }

        TypeRef<List<String>> typeRef = new TypeRef<List<String>>() {};
        List<String> titles = JsonPath.using(conf).parse(json).read("$.store.book[*].title", typeRef);
        System.out.println(titles);

    }
    static String json = """
            {
                "store": {
                    "book": [
                        {
                            "category": "reference",
                            "author": "Nigel Rees",
                            "title": "Sayings of the Century",
                            "price": 8.95
                        },
                        {
                            "category": "fiction",
                            "author": "Evelyn Waugh",
                            "title": "Sword of Honour",
                            "price": 12.99
                        },
                        {
                            "category": "fiction",
                            "author": "Herman Melville",
                            "title": "Moby Dick",
                            "isbn": "0-553-21311-3",
                            "price": 8.99
                        },
                        {
                            "category": "fiction",
                            "author": "J. R. R. Tolkien",
                            "title": "The Lord of the Rings",
                            "isbn": "0-395-19395-8",
                            "price": 22.99
                        }
                    ],
                    "bicycle": {
                        "color": "red",
                        "price": 19.95
                    }
                },
                "expensive": 10
            }""";
}

测试结果:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值