当前位置:首页 > 技术文章 > 正文内容

Json数据格式化问题_json数据格式化问题怎么解决

zonemu2个月前 (08-24)技术文章21

一 业务背景

需要将已保存的json字符串获取,并提取其中的某个字段按“,”拼接为字符串。

二 代码

2.1 实体

public class LangDataLimitDTO implements Serializable {

    /** 一级限制类别id */
    private Integer typeId;
    /** 一级限制类别名称 */
    private String typeName;

    public LangDataLimitDTO(Integer typeId, String typeName){
        this.typeId = typeId;
        this.typeName = typeName;
    }

2.2 格式转化代码

public String getLangLimitStr(){
        if(StringUtils.isEmpty(languageLimitJson)){
            return null;
        }
        List<LangDataLimitDTO> langDataLimitList = JsonUtils.fromJSON(languageLimitJson, new TypeReference<List<LangDataLimitDTO>>(){});
        if(CollectionUtils.isEmpty(langDataLimitList)){
            return null;
        }
        StringBuilder  sb = new StringBuilder();
        for(LangDataLimitDTO langDataLimitDTO : langDataLimitList){
            sb.append(langDataLimitDTO.getTypeName()).append(",");
        }
        return StringUtils.removeEnd(sb.toString(), ",");
    }

2.3 工具

	/**
	 *	
	 * 描述:将json字符串转成指定T类型的对象
	 * 示例:formJSON(jsonString,new MyTypeReference()<List<Map<String,Object>>>)
	 * @created 2014-4-7 上午10:04:20
	 * @since   v1.0.0 
	 * @param jsonString
	 * @param typeRef
	 * @return  T
	 */
	@SuppressWarnings("unchecked")
	public static final <T> T fromJSON(String jsonString, TypeReference<T> typeRef) {
		if (null == jsonString)
			return null;
		ByteArrayInputStream bais = new ByteArrayInputStream(jsonString.getBytes());
		try {
			ObjectInput in = serialization.deserialize(bais);
			return (T) in.readObject(typeRef);
		} catch (Exception e) {
			throw new RuntimeException("Json deserial error.", e);
		} finally {
			try {
				if (null != bais) {
					bais.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

2.4 序列化方式

private static final Serialization serialization = new JacksonSerialization();

三 问题

当使用getLangLimitStr()转化数据时,传入的合法的json串数据,返回的格式化对象为空的问题。

3.1 TypeReference分析

TypeReference为jackson包提供的用于处理泛型类型信息的工具,主要用于反序列化时明确指定目标类型,确保数据转换的准确性。

3.2 原因

1、反射实例化需求
Jackson默认通过反射调用无参构造器创建对象实例,再通过setter方法或字段注入填充属性。若类中仅存在有参构造器而无无参构造器,反射将无法实例化对象,导致反序列化失败。
2、框架设计约束
Jackson的ObjectMapper在反序列化时遵循标准JavaBean规范,要求目标类具备无参构造器以实现通用化处理。这种设计简化了反序列化流程,使其无需预知具体构造逻辑即可重建对象。
3、兼容性考量
无参构造器是Java序列化机制(如java.io.Serializable)和多数ORM框架(如Hibernate)的共同要求。Jackson保持这一约束可确保与其他技术栈的兼容性。

3.3 默认生成问题

默认无参构造方法的行为规则
1、自动生成条件
当类中未显式定义任何构造方法时,Java编译器会自动生成一个默认的无参构造方法(访问修饰符与类相同)。

public class User {} // 编译器会自动添加 public User() {}

2、手动定义覆盖
若类中已定义任意构造方法(包括有参构造),编译器不再自动生成无参构造方法。此时若需无参构造,必须显式声明

public class User {
    private String name;
    public User(String name) { this.name = name; }
    public User() {} // 必须手动添加
}

四 解决

4.1 添加无参构造

public class LangDataLimitDTO implements Serializable {

    /** 一级限制类别id */
    private Integer typeId;
    /** 一级限制类别名称 */
    private String typeName;

    public LangDataLimitDTO(){
    }
    public LangDataLimitDTO(Integer typeId, String typeName){
        this.typeId = typeId;
        this.typeName = typeName;
    }

4.2 实现反序列化器

public class ResponseDeserializer extends JsonDeserializer<Response> {
    @Override
    public Response deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
        Map<String, Map<String, String>> map = jsonParser.readValueAs(Map.class);
        Map<String, String> headerMap = map.get("headerMap");
        Map<String, String> apiMap = map.get("apiMap");

        return new Response(headerMap, apiMap);
    }
}

将反序列化器注册到 ObjectMapper 中:


public class ObjectMapperUtil {
    private static ObjectMapper objectMapper = new ObjectMapper();

    static {
        SimpleModule simpleModule = new SimpleModule("custom");
        simpleModule.addDeserializer(Response.class, new ResponseDeserializer());
        objectMapper.registerModule(simpleModule);
    }

    public static ObjectMapper getObjectMapper() {
        return objectMapper;
    }

    /**
     *
     * @param object
     * @return
     */
    public static String writeAsPrettyString(Object object) {
        try {
            return getObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
}

相关文章

「云原生」Containerd ctr,crictl 和 nerdctl 命令介绍与实战操作

一、概述作为接替Docker运行时的Containerd在早在Kubernetes1.7时就能直接与Kubelet集成使用,只是大部分时候我们因熟悉Docker,在部署集群时采用了默认的dockers...

02.Web大前端时代之:HTML5+CSS3入门系列~H5结构元素

Web大前端时代之:HTML5+CSS3入门系列:http://www.cnblogs.com/dunitian/p/5121725.html1.结构元素 可以理解为语义话标记,比如:以前这么写<...

(一)熟练HTML5+CSS3,每天复习一遍

前言学习网页的概念和分类,了解静态网页和动态网页的不同;了解网页浏览器的工作原理。了解HTML,XHTML,HTML5的概念,制作简单的HTML页面的开发。什么是网页可以在internet上通过网页浏...

web前端是什么,在哪些地方有应用,html和html5区别都在这里了

web前端是什么,在哪些地方有应用简介web前端开发技术什么是html、html5什么是css、css3什么是js,javascriptweb前端的应用大家好,我是ots_luo,很多小伙伴不知道we...

HTML5培训学习(简单明了)(html5教学视频教程)

这些事HTML5培训认为在学习HTML5前应该做好的准备,欢迎参考指正:为什么学习HTML5?软硬件环境介绍HTML5环境搭建常见问题解决掌握技能需求为什么学习HTML5?1:自从2010年HTML5...

2023 前端是否还需要 lodash ?(前端会被淘汰吗)

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!前言Lodash 是一个 JavaScri...