将嵌套List的Map转换为Json应该都没什么问题,使用Gson和Jackson都能实现,在Gson中使用new Gson().toJson()方法,在Jackson中使用new ObjectMapper().writeValueAsString()即可。

将json转换为形如Map>的时候遇到了一点问题,虽然返回类型是Map>但是,Map的value的值却并不是List,而是Integer类型的,这里面显然是有问题的,查看Jackson的源码和Gson的源码发现

将json反序列化为对象确实有两个方法,一种适用于泛型对象,一种适用于非泛型的一般对象。

使用Gson

在gson中将json字符串转反序列化为对象有两个方法:

/**

* This method deserializes the specified Json into an object of the specified class. It is not

* suitable to use if the specified class is a generic type since it will not have the generic

* type information because of the Type Erasure feature of Java. Therefore, this method should not

* be used if the desired type is a generic type. Note that this method works fine if the any of

* the fields of the specified object are generics, just the object itself should not be a

* generic type. For the cases when the object is of generic type, invoke

* {@link #fromJson(String, Type)}. If you have the Json in a {@link Reader} instead of

* a String, use {@link #fromJson(Reader, Class)} instead.

*

* @param the type of the desired object

* @param json the string from which the object is to be deserialized

* @param classOfT the class of T

* @return an object of type T from the string. Returns {@code null} if {@code json} is {@code null}.

* @throws JsonSyntaxException if json is not a valid representation for an object of type

* classOfT

*/

public T fromJson(String json, Class classOfT) throws JsonSyntaxException {

Object object = fromJson(json, (Type) classOfT);

return Primitives.wrap(classOfT).cast(object);

}

/**

* This method deserializes the specified Json into an object of the specified type. This method

* is useful if the specified object is a generic type. For non-generic objects, use

* {@link #fromJson(String, Class)} instead. If you have the Json in a {@link Reader} instead of

* a String, use {@link #fromJson(Reader, Type)} instead.

*

* @param the type of the desired object

* @param json the string from which the object is to be deserialized

* @param typeOfT The specific genericized type of src. You can obtain this type by using the

* {@link com.google.gson.reflect.TypeToken} class. For example, to get the type for

* {@code Collection}, you should use:

*

* Type typeOfT = new TypeToken>(){}.getType();

*

* @return an object of type T from the string. Returns {@code null} if {@code json} is {@code null}.

* @throws JsonParseException if json is not a valid representation for an object of type typeOfT

* @throws JsonSyntaxException if json is not a valid representation for an object of type

*/

@SuppressWarnings("unchecked")

public T fromJson(String json, Type typeOfT) throws JsonSyntaxException {

if (json == null) {

return null;

}

StringReader reader = new StringReader(json);

T target = (T) fromJson(reader, typeOfT);

return target;

}

观察fromJson(String json, Class classOfT)的注释:

It is not suitable to use if the specified class is a generic type since it will not have the generic type information because of the Type Erasure feature of Java

也就是说,由于Java泛型的擦除机制,这个方法不适用于传入泛型的类,比如Map,List等,这个时候可以用T fromJson(String json, Type typeOfT)替代。

下面还有一段话:

Note that this method works fine if the any of the fields of the specified object are generics, just the object itself should not be a generic type

** 注意:** 如果对象不是泛型的,只是字段是泛型的话这个方法是可以使用的

刚开始不太理解这句话,后来想通了,也就是类定义上不能带有泛型比如 public interface Map 这样的就不行,但是如果是下面这样的只有域上带有的泛型是可以:

static class JsonDemo{

private List list;

public List getList() {

return list;

}

public void setList(List list) {

this.list = list;

}

}

下面的fromJson(String json, Type typeOfT)就是专门提供给泛型类的对象使用的,如果你自己反序列化的对象带有泛型的话需要用这个方法。

使用Jackson

和gson一样,jackson也提供了两个方法,一个适用于普通的类,一个适用于泛型类,只不过jackson源码的注释没有Gson的丰富,从注释上看不出来,功能和Gson的一致。

/**

* Method to deserialize JSON content from given JSON content String.

*

* @throws IOException if a low-level I/O problem (unexpected end-of-input,

* network error) occurs (passed through as-is without additional wrapping -- note

* that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS}

* does NOT result in wrapping of exception even if enabled)

* @throws JsonParseException if underlying input contains invalid content

* of type {@link JsonParser} supports (JSON for default case)

* @throws JsonMappingException if the input JSON structure does not match structure

* expected for result type (or has other mismatch issues)

*/

@SuppressWarnings("unchecked")

public T readValue(String content, Class valueType)

throws IOException, JsonParseException, JsonMappingException

{

return (T) _readMapAndClose(_jsonFactory.createParser(content), _typeFactory.constructType(valueType));

}

/**

* Method to deserialize JSON content from given JSON content String.

*

* @throws IOException if a low-level I/O problem (unexpected end-of-input,

* network error) occurs (passed through as-is without additional wrapping -- note

* that this is one case where {@link DeserializationFeature#WRAP_EXCEPTIONS}

* does NOT result in wrapping of exception even if enabled)

* @throws JsonParseException if underlying input contains invalid content

* of type {@link JsonParser} supports (JSON for default case)

* @throws JsonMappingException if the input JSON structure does not match structure

* expected for result type (or has other mismatch issues)

*/

@SuppressWarnings({ "unchecked", "rawtypes" })

public T readValue(String content, TypeReference valueTypeRef)

throws IOException, JsonParseException, JsonMappingException

{

return (T) _readMapAndClose(_jsonFactory.createParser(content), _typeFactory.constructType(valueTypeRef));

}

简单实验

使用两种方式反序列一个json,使用Class来反序列化泛型类型的对象,在printType的时候会出现ClassCastException类型转换异常。

package org.xuan;

import com.fasterxml.jackson.core.type.TypeReference;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.google.common.collect.Maps;

import com.google.common.reflect.TypeToken;

import com.google.gson.Gson;

import java.io.IOException;

import java.util.Arrays;

import java.util.List;

import java.util.Map;

/**

* Created by zhaohongxuan

*/

public class JsonTest {

private static ObjectMapper mapper = new ObjectMapper();

private static Gson gson = new Gson();

public static void main(String[] args) throws IOException {

Map> map = Maps.newHashMap();

map.put("one", Arrays.asList(10001L, 10002L, 10003L, 10004L));

map.put("two", Arrays.asList(20001L, 20002L, 20003L, 20004L));

map.put("three", Arrays.asList(30001L, 30002L, 30003L, 30004L));

map.put("four", Arrays.asList(40001L, 40002L, 40003L, 40004L));

String json = new Gson().toJson(map);

System.err.println("=======================错误示范=====================");

//Gson

Map> mapResult = gson.fromJson(json,Map.class);

System.out.println("通过Gson转换...");

// printType(mapResult);

System.out.println(mapResult);

//Json

Map> jsonMapResult = mapper.readValue(json,Map.class);

System.out.println("通过Jackson转换...");

// printType(jsonMapResult);

System.out.println(jsonMapResult);

System.out.println("=======================正确做法=====================");

//Gson

Map> mapResult1 = gson.fromJson(json,new TypeToken>>(){}.getType());

System.out.println("通过Gson转换...");

printType(mapResult1);

System.out.println(mapResult1);

//Json

ObjectMapper mapper = new ObjectMapper();

Map> jsonMapResult1 = mapper.readValue(json,new TypeReference< Map>>() {});

System.out.println("通过Jackson转换...");

printType(jsonMapResult1);

System.out.println(jsonMapResult1);

}

public static void printType(Map> map){

for (Map.Entry> entry: map.entrySet()){

System.out.println("key 类型:"+entry.getKey().getClass()+", value类型:"

+entry.getValue().getClass()+", List中元素类型"+entry.getValue().get(0).getClass());

}

}

}

总 结

在Gson中:

如果使用fromJson(String json, Class classOfT)来反序列化Map的话,不会造成编译错误,返回的类型就会变化,Long类型变成了Double类型,使用的时候就会出现异常,例如在遍历Map的entrySet的时候就会出现异常。

java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Long

因此:

反序列化泛型对象如Map等需要使用 fromJson(String json, Type typeOfT)

一般对象使用fromJson(String json, Class classOfT)

在Jackson中:

如果使用T readValue(String content, Class valueType)来反序列化Map的话,返回的类型就会由Long类型变成了Integer类型。

反序列化泛型对象如Map等需要使用 T readValue(String content, TypeReference valueTypeRef)

一般对象使用T readValue(String content, Class valueType)

json序列化 java对象_Java中将JSON反序列化为泛型对象相关推荐

  1. json 反射java 实体_Java 将JSON反射到实体类

    通过服务间调用拿到的数据返回的格式是JSON,如果你当前这个服务有实体数据类型可以对应上,那么就可以轻松愉快的搞定. 如果数据格式对不上,例如这个JSON里面有些数据是我们不想要的,这样我们实体的数据 ...

  2. json序列化 java对象_Json 数据反序列化为Java对象

    前言:我们在项目中经常用到的是Json格式的数据,如果是将一个被Jackson转化为JSON数据格式的Java对象进行操作,我们就需要将JSON数据再反序列化为Java对象. 1.实体对象 packa ...

  3. 是否可以将 json 反序列化为 dynamic 对象?

    咨询区 jswanson: 是否有方法可以将 json 反序列化为 dynamic 对象,如果可以实现的话,那我就可以省去很多冗余类. 回答区 Tom Peplow: 如果你用 Json.NET 的话 ...

  4. json与java反射_Java 对象的 Json 化与反 Json 化

    最近在家里修习 Java 这项技能,估计快点满技能点儿了,很开心.不过遇到了一个问题,困扰了我一阵子.问题是这样的,我要写 Android App,与服务器交互.大家都知道 Javascript 不知 ...

  5. kryo java_优化Java序列化– Java,XML,JSON,Kryo,POF

    kryo java 也许我很天真,但是我一直认为Java序列化肯定是将Java对象序列化为二进制形式的最快,最有效的方法. 毕竟Java是第7个主要发行版,所以这不是新技术,而且由于每个JDK似乎都比 ...

  6. 优化Java序列化– Java,XML,JSON,Kryo,POF

    也许我很天真,但是我一直认为Java序列化肯定是将Java对象序列化为二进制形式的最快,最有效的方法. 毕竟Java是第7个主要发行版,所以这不是新技术,并且由于每个JDK似乎都比上一个快,因此我错误 ...

  7. 将$type添加到System.Text.Json序列化中,就像Newtonsoft那样用于动态对象属性

    目录 介绍 用户故事5:在System.Text.Json JsonSerializer中支持动态类型 演示项目和测试 修改模型方法 包装方法 总结 Pro Coders团队最近将一个大型项目从New ...

  8. java json的使用方法_JAVA编写JSON常用的三种方法

    JAVA编写JSON常用的三种方法 Szx • 2019 年 11 月 15 日 1.jsonlib需要引入的包也多,代码也相对多一些. 2.Gson:谷歌的 3.FastJson:阿里巴巴的,这几个 ...

  9. 解决MVC Json序列化的循环引用问题/EF Json序列化循引用问题---Newtonsoft.Json

    1..Net开源Json序列化工具Newtonsoft.Json中提供了解决序列化的循环引用问题: 方式1:指定Json序列化配置为 ReferenceLoopHandling.Ignore 方式2: ...

  10. json序列化c语言,C语言JSON序列化/反序列化

    最近想找一个C语言处理嵌套结构体和结构体数组的json库,理想的是能够很容易处理复杂结构体嵌套,并且使用简单的,但是没找到比较合适的,于是打算自己封装一个: 两个问题: C语言结构体本身没有元数据,这 ...

最新文章

  1. matlab文件启动位置,matlab中uigetfile()设置默认路径
  2. html电池百分比,显示电池百分比在哪设置
  3. ubuntu查看内存或cpu使用情况
  4. 机器学习——深度学习(Deep Learning)经典资料
  5. 彻底搞懂---三握四挥
  6. 面试总是死在网络协议,我该怎么办?
  7. Modbus驱动库—libmodbus驱动库的使用
  8. 牛蛙怎么做好吃 牛蛙的家常做法
  9. 全国区号码表(绝对全)
  10. jquery ztree 皮肤(官网介绍)
  11. S3C2440原理图导读
  12. win7计算机无法连接投影仪,win7系统无法连接投影仪的解决方法
  13. html元素在模块中心显示,DW怎么设置DIV模块在页面中居中 DW如何设置网页打开绝对居中?...
  14. python打印一整年的日历
  15. Python:实现骰子游戏
  16. javascript 神经网络
  17. 嵌入式linux--电子相册
  18. 前端培训班出身——吐槽下16年的艰辛
  19. 方法和数组 - 打好基础很重要
  20. 图书系统(轻松上手)

热门文章

  1. uni-ap开发开发小程序 怎么使用阿里云播放器
  2. 19华为软件精英挑战赛止步复赛
  3. C语言程序设计流程图详解
  4. NAS服务器和文件服务器区别
  5. PPT 字体的玩法(师从于珞珈老师)
  6. Java实现文件复制功能
  7. CUDA C 编程/Nsight可视化
  8. 数据库-创建数据库-创建数据表
  9. 基于python的图书管理系统设计与实现论文_图书管理系统的设计与实现图书管理系统论文...
  10. 【项目管理】记第一次出差到客户现场推进项目验收感悟-后续项目验收篇