首页IT科技object to(ObjectMapper转化对象常用方法(转LIst、Map,以及Type、JavaType、constructType的学习))

object to(ObjectMapper转化对象常用方法(转LIst、Map,以及Type、JavaType、constructType的学习))

时间2025-09-15 13:59:47分类IT科技浏览10313
导读:1. 前言 在工作中,必然少不了JSON转化对象,而一般来说JSON的转化,要么就是在controller层,springboot帮忙转化好了,要么就是很简单的常转List、Map等等。...

1. 前言

在工作中                   ,必然少不了JSON转化对象                             ,而一般来说JSON的转化        ,要么就是在controller层              ,springboot帮忙转化好了                              ,要么就是很简单的常转List                   、Map等等                   。

而在学习Feign的时候             ,可以自定义Decoder解析器         ,对返回报文做个性化处理                              ,但这个时候                  ,对方返回的数据就需要自己将json字符串转为对应的对象了                             。

而在自己转化的时候    ,发现ObjectMapper提供如下两个方法:

一个是class类型的参数                             ,一个是JavaType类型的参数                       ,而该decode方法中,只有Type类型        。

这个时候不经会发问几个问题:

如何将feign请求到的返回数据转为对象呢? Type类型是什么东西                        ,在decoder方法中要怎么转化呢? 如果可以转化了                            ,那复杂的对象又要如何书写代码呢?

上述问题是在我学习feign自定义解析器解析返回报文时候出现的    ,如何自定义解析一个复杂的报文

从而衍生出:ObjectMapper转化对象方法到底有哪些?

2. 先说结论

通常转对象使用方式是 objectMapper.readValue(String jsonStr, Class<T> clazz); 转List                             、Map

使用方式是 objectMapper.readValue(String jsonStr, TypeReference valueTypeRef); 例子如下:

List: objectMapper.readValue(json, new TypeReference>() {});

Map: objectMapper.readValue(json, new TypeReference<Map<String, JsonPerson>>() {}); 使用constructType方式 转化对象                   ,就是提前把需要转成的对象的类型先构造出来                             ,之后就交给objectMapper直接反序列化即可              。 常用创建类型的方法: objectMapper.constructType() 直接创建对应的类型出来        ,如创建单对象的类型:objectMapper.constructType(T.class) objectMapper.getTypeFactory().constructParametricType() 创建带有参数化的类型              ,如转List:objectMapper.getTypeFactory().constructParametricType(List.class, T.class).

3. 快速入门

准备实体类如下: @Getter @ToString static class JsonPerson { private String name; private String pwd; }

1. 常用转对象        、List              、Map(复习常用的方式)

对象                              ,直接指明对象的class类

private static void json(ObjectMapper objectMapper) throws JsonProcessingException { String json = "{\n" + " \"name\":\"test-name\",\n" + " \"pwd\":\"test-pwd\"\n" + " }"; final JsonPerson jsonPerson = objectMapper.readValue(json, JsonPerson.class); System.out.println(jsonPerson); }

List

一种直接指明ArrayList的class类 // 指明ArrayList的class类的方式 private static void json2(ObjectMapper objectMapper) throws JsonProcessingException { String json2 = "[{\n" + " \"name\":\"test-name\",\n" + " \"pwd\":\"test-pwd\"\n" + " }]"; final List<JsonPerson> jsonPersonList2 = objectMapper.readValue(json2, ArrayList.class); System.out.println(jsonPersonList2); }

另一种使用TypeReference(一般都是用这种)

private static void json3(ObjectMapper objectMapper) throws JsonProcessingException { String json3 = "[{\n" + " \"name\":\"test-name\",\n" + " \"pwd\":\"test-pwd\"\n" + " }]"; final List<JsonPerson> jsonPersonList = objectMapper.readValue(json3, new TypeReference<List<JsonPerson>>() {}); System.out.println(jsonPersonList); }

Map跟List同理             ,有两种方式

一种直接指明Map的class类 private static void json4(ObjectMapper objectMapper) throws JsonProcessingException { String json4 = "{\n" + " \"TestData1\": {\n" + " \"name\": \"test-name\",\n" + " \"pwd\": \"test-pwd\"\n" + " },\n" + " \"TestData2\": {\n" + " \"name\": \"test-name2\",\n" + " \"pwd\": \"test-pwd2\"\n" + " }\n" + "}"; final Map<String, JsonPerson> jsonPersonMap = objectMapper.readValue(json4, Map.class); System.out.println(jsonPersonMap); }

另一种使用TypeReference(一般都是用这种)

private static void json5(ObjectMapper objectMapper) throws JsonProcessingException { String json5 = "{\n" + " \"TestData1\": {\n" + " \"name\": \"test-name\",\n" + " \"pwd\": \"test-pwd\"\n" + " },\n" + " \"TestData2\": {\n" + " \"name\": \"test-name2\",\n" + " \"pwd\": \"test-pwd2\"\n" + " }\n" + "}"; final Map<String, JsonPerson> jsonPersonMap = objectMapper.readValue(json5, new TypeReference<Map<String, JsonPerson>>() { }); System.out.println(jsonPersonMap); }

2. 使用constructType方式

constructType方式:根据输入的参数先构建出需要转化的java类型

直接看例子:

先看普通的对象private static void json6(ObjectMapper objectMapper) throws JsonProcessingException { String json6 = "{\n" + " \"name\":\"test-name\",\n" + " \"pwd\":\"test-pwd\"\n" + " }"; // 构建JsonPerson类型的转化对象 final JavaType javaType = objectMapper.constructType(JsonPerson.class); // 告诉objectMapper:json6字符串需要转为 javaType的类型         ,即就是JsonPerson类 final JsonPerson jsonPerson = objectMapper.readValue(json6, javaType); System.out.println(jsonPerson); }

有人就会说                              ,这很弱鸡呀                  ,还不如直接objectMapper.readValue(json, class)    ,别着急                             ,上述是转简单对象的操作而已                       ,这只是先让大家初步认识constructType                              。

先看例子中objectMapper.constructType(JsonPerson.class);这个方法源码:

public JavaType constructType(Type t) { // 先校验非空 _assertNotNull("t", t); // 使用类型工厂 创建t类型的类型 return _typeFactory.constructType(t); }

此时产生第一个问题:Type类是什么,如果没上述例子                        ,第一次看见这个方法                            ,我们怎么知道要传入什么参数呢

需要补充一下其他知识点    ,Type是什么

Type是Java 编程语言中所有类型的公共高级接口             。 简单来说:所有的数据类型的类型都是Type, Class也是继承自Type的

                   ,再通俗来说                             ,Type就是所有数据类型的“爹                   ”         。 Type的直接子接口(也就是Type具体有哪些类型):

1.ParameterizedType: 表示一种参数化的类型        ,比如Collection              ,即普通的泛型                              。

2.TypeVariable:是各种类型变量的公共父接口                              ,就是泛型里面的类似T                              、E                  。

3.GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型             ,比如List<>[]         ,T[]这种    。

4.WildcardType:代表一种通配符类型表达式                              ,类似? super T这样的通配符表达式                             。 下面是找到比较好并且参考的资料, 大家看看他们写的代码例子                  ,应该可以理解这高深的话语了: 对java-Type的理解 java中的Type TYPE JAVA类型

看完第六大点    ,就可以解决第五大点的问题                             ,如果还不能理解                       ,就通俗到把Type就认为是类型,constructType就是理解为构造要转化什么java类型                       。

接下来我们看第二个例子:转List对象

private static void json7(ObjectMapper objectMapper) throws JsonProcessingException { String json7 = "[{\n" + " \"name\":\"test-name\",\n" + " \"pwd\":\"test-pwd\"\n" + " }]"; // 获取Type的工厂 final TypeFactory typeFactory = objectMapper.getTypeFactory(); // 创建 JsonPerson的Type类型 final JavaType jsonPersonType = typeFactory.constructType(JsonPerson.class); // 因为转化的是List<JsonPerson>类型 // 则也就是要创建有参数的Type类型 // 即 constructParametricType(List.class, jsonPersonType)---> List<JsonPerson> final JavaType javaType = typeFactory.constructParametricType(List.class, jsonPersonType); // 反序列化 final List<JsonPerson> jsonPersonList = objectMapper.readValue(json7, javaType); // 得到结果集 System.out.println(jsonPersonList); }

若上述的注释可以看的懂                        ,其实也可以用下面简单方式(已有api):

private static void json8(ObjectMapper objectMapper) throws JsonProcessingException { String json8 = "[{\n" + " \"name\":\"test-name\",\n" + " \"pwd\":\"test-pwd\"\n" + " }]"; // 获取Type的工厂 final TypeFactory typeFactory = objectMapper.getTypeFactory(); // 因为转化的是List<JsonPerson>类型 // 直接API constructCollectionType 创建集合类型 // 得到Collection<T>类型 final JavaType javaType = typeFactory.constructCollectionType(List.class, JsonPerson.class); // 反序列化 final List<JsonPerson> jsonPersonList = objectMapper.readValue(json8, javaType); // 得到结果集 System.out.println(jsonPersonList); }

接下来第三个例子:转Map<String, JsonPerson>类型                            ,其实也是大同小异    ,也是两种方式                   ,细节如下:

private static void json9(ObjectMapper objectMapper) throws JsonProcessingException { String json9 = "{\n" + " \"TestData1\": {\n" + " \"name\": \"test-name\",\n" + " \"pwd\": \"test-pwd\"\n" + " },\n" + " \"TestData2\": {\n" + " \"name\": \"test-name2\",\n" + " \"pwd\": \"test-pwd2\"\n" + " }\n" + "}"; // 获取Type的工厂 final TypeFactory typeFactory = objectMapper.getTypeFactory(); // 因为转化的是Map<String, JsonPerson>类型 // 主类型是Map.class 然后就是key value的类型:String.class JsonPerson.class final JavaType javaType = typeFactory.constructParametricType(Map.class, String.class, JsonPerson.class); // 也可以使用这种方式 // final JavaType javaType = typeFactory.constructMapType(Map.class, String.class, JsonPerson.class); // 反序列化 final Map<String,JsonPerson> jsonPersonMap = objectMapper.readValue(json9, javaType); // 得到结果集 System.out.println(jsonPersonMap); }

为了节约时间                             ,我们将直接给个高级的例子:转为JsonResponse<Map<String,List<JsonPerson>>> 对象:

// 为什么需要这一层呢? // 1. 接口的返回值将会封装为下述结构体        ,当调用方接受到报文的时候              ,可以直接优先判断code即返回码                              ,可快速知道这次请求到底是成功还是失败 // 若失败             ,则直接读取错误信息message         ,若成功                              ,直接读取data数据。 // 2. 也是给会报错的代码打个标志                  ,若出错误了    ,可以快速根据code返回码                             ,判断对应代码是那段出问题                       ,快速定位                        。 @Getter @ToString static class JsonResponse<T> { private String code; private String message; private T data; } @Getter @ToString static class JsonPerson { private String name; private String pwd; } private static void json11(ObjectMapper objectMapper) throws JsonProcessingException { String json11 = "{\n" + " \"code\": \"success\",\n" + " \"data\": {\n" + " \"TestData1\": [\n" + " {\n" + " \"name\": \"test-data-name-one\",\n" + " \"pwd\": \"test-data-pwd-one\"\n" + " },\n" + " {\n" + " \"name\": \"test-data-name-two\",\n" + " \"pwd\": \"test-data-pwd-two\"\n" + " }\n" + " ],\n" + " \"TestData2\": [\n" + " {\n" + " \"name\": \"test-data2-name-one\",\n" + " \"pwd\": \"test-data2-pwd-one\"\n" + " },\n" + " {\n" + " \"name\": \"test-data2-name-two\",\n" + " \"pwd\": \"test-data2-pwd-two\"\n" + " }\n" + " ]\n" + " }\n" + "}"; // 获取Type的工厂 final TypeFactory typeFactory = objectMapper.getTypeFactory(); // 因为转化的是JsonResponse<Map<String,List<JsonPerson>>> 类型 由里到外,一层层创建对应类型 // 先创建List<JsonPerson> 类型 final JavaType listJsonPersonType = typeFactory.constructCollectionType(List.class, JsonPerson.class); // 由于 constructMapType方法有如下两种: // 1. constructMapType(Class<? extends Map> mapClass,Class<?> keyClass, Class<?> valueClass) // 2. constructMapType(Class<? extends Map> mapClass, JavaType keyType, JavaType valueType) // 对应的key value入参                        ,要不都是class                            ,要不都是JavaType 类型 // 因此需要把Map中的String先创建 JavaType 类型 final JavaType stringType = typeFactory.constructType(String.class); // 再创建Map<String,List<JsonPerson>> 类型 final JavaType mapType = typeFactory.constructMapType(Map.class, stringType, listJsonPersonType); // 再创建JsonResponse<Map<String,List<JsonPerson>>> 类型 final JavaType lastType = typeFactory.constructParametricType(JsonResponse.class, mapType); // 反序列化 final JsonResponse<Map<String,List<JsonPerson>>> jsonResponse = objectMapper.readValue(json11, lastType); // 得到结果 System.out.println(jsonResponse); }

4. 其他

对于怎么实现Feign的自定义Decoder解析器    ,等写到Feign知识点的时候再说吧                   ,提前剧透一下                             ,Feign真的很有意思                            。
声明:本站所有文章        ,如无特殊说明或标注              ,均为本站原创发布    。任何个人或组织                              ,在未征得本站同意时             ,禁止复制             、盗用         、采集                              、发布本站内容到任何网站                  、书籍等各类媒体平台                   。如若本站内容侵犯了原著者的合法权益         ,可联系我们进行处理                             。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
winrar多线程解压(pigz命令 – 多线程的解压缩文件) 404页面的设计与优化(如何提升用户体验和SEO排名)