Jackson @JsonUnwrapped注解扁平化 序列化反序列化数据

参考资料

  1. Jackson 2.x 系列【7】注解大全篇三
  2. @JsonUnwrapped 以扁平的数据结构序列化/反序列化属性
  3. Jackson扁平化处理对象

目录

  • 一. 前期准备
    • 1.1 前端
    • 1.2 实体类
    • 1.3 Controller层
  • 二. 扁平化序列反序列化数据
    • 2.1 序列化数据
    • 2.2 反序列化数据
  • 三. 前缀后缀处理属性同名
  • 四. Map数据的处理


一. 前期准备

1.1 前端

$(function() {
    bindEvent();
});

function bindEvent() {

    $("#btn").click(() => {
		
		// 准备提交到后端的数据
        const jsonData = {
            id: "112",
            name: "前端来的name",
            houseId: "前端来的houseId",
            address: "前端来的address",
            blogId: "前端来的blogId",
            blogName: "前端来的blogName"
        };

        $.ajax({
            url: `/test34/get_data`,
            type: 'POST',
            data: JSON.stringify(jsonData),
            contentType: 'application/json;charset=utf-8',
            success: function (data, status, xhr) {
                console.log(data);
            }
        });
    });
}

1.2 实体类

import com.fasterxml.jackson.annotation.*;
import lombok.Data;

@Data
public class Test34Entity {

    private String id;

    private String name;

    @JsonUnwrapped
    private House house;

    @JsonUnwrapped
    private BlogTag blogTag;
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class House {

    private String houseId;

    private String address;
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class BlogTag {

    private String blogId;

    private String blogName;
}

1.3 Controller层

mport org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import java.io.IOException;

@Controller
@RequestMapping("/test34")
public class Test34Controller {

    @GetMapping("/init")
    public ModelAndView init() {

        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("test34");

        return modelAndView;
    }

    @PostMapping("/get_data")
    public ResponseEntity<Test34Entity> getData(@RequestBody Test34Entity data) throws IOException {

        System.out.println(data);

        Test34Entity entity  = new Test34Entity();
        
        // 设置基本类型的属性值
        entity.setId("1355930");
        entity.setName("贾飞天");
    
        // 设置自定义类型(bean)的属性值
        entity.setHouse(new House("house_id_1", "地球"));
        entity.setBlogTag(new BlogTag("tag_id_1", "tag_name_1"));
        
        return ResponseEntity.ok(entity);
    }
}

二. 扁平化序列反序列化数据

@JsonUnwrapped注解只能处理Bean类型的数据,List<Bean>Map<键,Bean>等数据类型是无法处理的。

2.1 序列化数据

  • 给需要扁平化处理的Bean添加@JsonUnwrapped注解
  • 需要扁平化处理的Bean还需要有构造函数,必须有构造函数,否则后台接收数据时会报错。
  • 这样前台扁平化提交数据的时候,后台可以用一个类组合多个类的方式接收数据

⏹使用@JsonUnwrapped注解之前

  • 前台需要提交如下的数据结构,前台的数据结构层次需要根据后台的Bean结构层次调整
const jsonData = {
    id: "112",
    name: "前端来的name",
    house: {
		houseId: "前端来的houseId",
    	address: "前端来的address"
	},
    blogTag: {
    	blogId: "前端来的blogId",
	    blogName: "前端来的blogName"	
	}
};
  • 后台使用的数据结构
@Data
public class Test34Entity {

    private String id;
    private String name;
    
    private House house;
    private BlogTag blogTag;
}

⏹使用@JsonUnwrapped注解之后,前台无需根据后台的Bean结构来组装数据,直接扁平化提交即可,对于一些不使用Vue,React框架等前台框架的项目有用,能写起来更简单。

  • 前台数据结构
const jsonData = {
    id: "112",
    name: "前端来的name",
    houseId: "前端来的houseId",
    address: "前端来的address",
    blogId: "前端来的blogId",
    blogName: "前端来的blogName"
};
  • 后台数据结构
@Data
public class Test34Entity {

    private String id;

    private String name;

    @JsonUnwrapped
    private House house;

    @JsonUnwrapped
    private BlogTag blogTag;
}

⏹实质上是Jackson 通过@JsonUnwrapped注解将HouseBlogTag属性拍扁放到Test34Entity实体类中。右下图可以看到,数据自动完成了封装。

在这里插入图片描述

2.2 反序列化数据

⏹不使用@JsonUnwrapped注解,前台的json数据结构和后台的Bean相同。

在这里插入图片描述

⏹使用@JsonUnwrapped注解,后台的嵌套的Bean属性被展平后返回给前台。

在这里插入图片描述


三. 前缀后缀处理属性同名

😅如下图所示,由于Test34Entity类和组合类的属性名相同,从而导致属性丢失。

在这里插入图片描述

⏹可以在@JsonUnwrapped注解上指定前缀或后缀来避免属性重名问题

import com.fasterxml.jackson.annotation.*;
import lombok.Data;

@Data
public class Test34Entity {

    private String id;

    private String name;

    @JsonUnwrapped(prefix = "house_", suffix = "_suffix")
    private House house;

    @JsonUnwrapped(prefix = "blog_", suffix = "_suffix")
    private BlogTag blogTag;

    @Data
    public static class BlogTag {

        private String id;

        private String name;
    }

    @Data
    public static class House {

        private String id;

        private String address;
    }
}

⏹反映到前端的截图如下所示

在这里插入图片描述


四. Map数据的处理

😅@JsonUnwrapped注解原生不支持Map,由下图所示,前台得到的json中,blogTagMap属性依然存在。

在这里插入图片描述

⏹将Test34Entity 实体类,进行如下修改

  • 使用@JsonAnySetter@JsonAnyGetter注解
  • addBlogTagMap,getBlogTagMap,setBlogTagMap方法名中的blogTagMap部分和属性名blogTagMap保持一致。
import com.fasterxml.jackson.annotation.*;
import lombok.Data;

import java.util.Map;

@Data
public class Test34Entity {

    private String id;

    private String name;

    private Map<String, BlogTag> blogTagMap;

    @JsonAnySetter
    public void addBlogTagMap(String key, BlogTag value) {
        blogTagMap.put(key, value);
    }

    @JsonAnyGetter
    public Map<String, BlogTag> getBlogTagMap() {
        return blogTagMap;
    }

    public void setBlogTagMap(Map<String, BlogTag> blogTagMap) {
        this.blogTagMap = blogTagMap;
    }
}

⏹然后在前台查看效果,可以看到外侧的blogTagMap属性名不见了。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/519071.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Pillow教程10:设计博文的文字背景封面图,再也不担心找不到不素材了

---------------Pillow教程集合--------------- Python项目18&#xff1a;使用Pillow模块&#xff0c;随机生成4位数的图片验证码 Python教程93&#xff1a;初识Pillow模块&#xff08;创建Image对象查看属性图片的保存与缩放&#xff09; Pillow教程02&#xff1a;图片的裁…

C#中ref和out相关知识点

知识点一&#xff1a; 知识点二&#xff1a; 知识点三&#xff1a; 测试&#xff1a; 总结&#xff1a; 练习

逐步学习Go-WaitGroup【连字都懒得写了,直接Show my Code】

package waitgroup_testimport ("fmt""runtime""sync""testing""time""github.com/stretchr/testify/assert" )// 这是对Go语标准库中sync包下的WaitGroup的描述。// WaitGroup用于等待一组并发的goroutine结结束…

理解VAE,可视化

引言 本文主要摘抄自&#xff1a;Understanding Variational Autoencoders (VAEs), Joseph Rocca, Sep 24, 2019&#xff0c;同时会加一些自己的理解和对原文的解释。 关于数据生成&#xff0c;目前深度生成模型中主流的有&#xff1a; 生成对抗网络——GANs&#xff0c;这是…

【Python的第三方库】flask

1. Flask是什么&#xff1f; 基于python的web后端开发轻量级框架&#xff1b; 基于MVT设计模式即Models,Views,Templates(html模板语言) 2.中文文档&#xff1a; https://dormousehole.readthedocs.io/en/2.1.2/index.html 3.依赖3个库&#xff1a; Jinja2 模版&#xff1…

armlinux-外部中断

s3c2440的中断框图 如果我们单纯配置一个按键的外部中断&#xff0c;就不存在子中断与优先级的问题。 由于是按键的外部中断&#xff0c;通过引脚的高低电平来触发。所以我们要先配置引脚的功能。 我们使用按键1&#xff0c;终端源为EINT8&#xff0c;对应引脚GPG0 通过用户手…

物联网实战--入门篇之(八)嵌入式-空气净化器

目录 一、风扇调速 二、通讯协议 三、净化器运行逻辑 一、风扇调速 单片机是不能直接驱动电机的&#xff0c;因为主芯片的驱动电流比较小(50mA左右)&#xff0c;他们之间正常还要有个电机驱动器&#xff0c;常用的有TB6612、L298和L9110等&#xff0c;目前项目用的这个电机它…

全国航空机场分布矢量数据/旅游景点poi/全国港口码头分布/地铁站分布/火车站分布/POI矢量数据

民用航空机场是指针对包括跑道型机场、表面直升机场、高架直升机场、船上直升机场、直升机水上平台、滑翔机场、水上机场、有人操纵气球施放场以及其他专供民用航空器起降的划定区域。民用航空机场分为通用航空机场和公共运输机场&#xff1b;不包括临时机场和专用机场。 根据中…

谷歌修复了安卓中的 28 个漏洞和 Pixel 设备中的 25 个错误

关注公众号&#xff1a; 网络研究观 获取更多信息 本周&#xff0c;谷歌工程师修复了Android 中的 28 个漏洞和 Pixel 设备中的 25 个错误&#xff0c;其中包括两个已经被利用的问题。 据报道&#xff0c;网络取证已利用 Google Pixel 0day 漏洞在没有 PIN 码的情况下解锁智能…

【附下载】2024全行业数字化转型企业建设解决方案PPT合集

精品推荐&#xff0c;2024全行业数字化转型企业建设解决方案PPT合集&#xff0c;精品PPT源格式共21份。 以下是资料目录&#xff0c;如需下载&#xff0c;请前往星球获取&#xff1a; 1.制造业数字化转型解决方案及应用.pptx 2.医院数字化网络解决方案.pptx 3.食品饮料工厂数字…

Vuex(vue 项目中实现 频繁、大范围数据共享的技术方案)

参考文档(点击查看) 好处 1.数据的存取一步到位&#xff0c;不需层层传递 2.数据的流动非常清晰 3.存储在Vuex中的数据都是响应式的&#xff08;数据更新后&#xff0c;使用数据的组件都会自动更新&#xff09; Vuex基础配置 npm i vuex3.6.2state中用来存储数据&#xff0c…

js中使let关键字报错,改用var关键字解决

js中使let关键字报错,改用var关键字解决 项目场景&#xff1a;问题描述原因分析&#xff1a;解决方案&#xff1a;总结 项目场景&#xff1a; 使用 let 关键字报错&#xff0c;报错信息为&#xff1a; Uncaught ReferenceError: maxNum is not defined at getMaxNum (4-3.htm…

专题三——二分算法

目录 原理 模板 朴素二分算法 非朴素二分算法 一二分查找 二在排序数组中查找元素的第一个和最后一个位置 三点名 四x的平方根 五搜索插入位置 六山脉数组的峰顶索引 七寻找峰值 八寻找旋转排序数组中的最小值 原理 定义两个指针&#xff1a;left指向数组第一个元…

Layui三级联动插件使用方法

Layui高版本中没有在提供三级联动这个动画了&#xff0c;而是封装成了一个插件&#xff0c;使用方式也很简单 官网 省市县区三级联动下拉选择器 layarea - Layui 第三方扩展组件平台 (layuion.com)https://dev.layuion.com/extend/layarea/#doc html页面约束 整个选择器需要…

【保姆级讲解如何安装与配置Node.js】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

HTML1:html基础

HTML 冯诺依曼体系结构 运算器 控制器 存储器 输入设备 输出设备 c/s(client客户端) 客户端架构软件 需要安装,更新麻烦,不跨平台 b/s(browser浏览器) 网页架构软件 无需安装,无需更新,可跨平台 浏览器 浏览器内核: 处理浏览器得到的各种资源 网页: 结构 HTML(超…

SRS 实时视频服务器搭建及使用

一、SRS 介绍 SRS是一个开源的&#xff08;MIT协议&#xff09;简单高效的实时视频服务器&#xff0c;支持RTMP、WebRTC、HLS、HTTP-FLV、SRT、MPEG-DASH和GB28181等协议。 SRS媒体服务器和FFmpeg、OBS、VLC、 WebRTC等客户端配合使用&#xff0c;提供流的接收和分发的能力&am…

【机器学习】机器学习创建算法第4篇:K-近邻算法,学习目标【附代码文档】

机器学习&#xff08;算法篇&#xff09;完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;机器学习算法课程定位、目标&#xff0c;K-近邻算法定位,目标,学习目标,1 什么是K-近邻算法,1 Scikit-learn工具介绍,2 K-近邻算法API。K-近邻算法&#xff0c;1.4 …

Java:接口应用(Clonable 接口和深拷贝)

目录 1.引例2.Object中clone方法的实现3.Cloneable接口讲解4.深拷贝和浅拷贝4.1浅拷贝4.2深拷贝 1.引例 Java 中内置了一些很有用的接口, Clonable 就是其中之一. Object 类中存在一个 clone 方法, 调用这个方法可以创建一个对象的 “拷贝”. 但是要想合法调用 clone 方法。必…

Qt | Qt 的重要文件简介(推荐)

一、项目文件(pro 文件)及其语法 1、项目文件(pro 文件)的作用是列举项目中的源文件, 2、pro 文件的语法形式为:“变量 操作符 值”,比如 QT += widgets,多个值之间使用空格分开。 3、pro 文件的注释:从“#”开始,直至本行结束。 4、pro 文件的操作符见下表 5、pro 文…