// 这是Kotlin代码,Java也是一样原理,都是用@JsonView实现单向透明。// 原理:使用@JsonView和withView(JvXxx) 让jackson从某一方向扫描时,直接忽略某些字段。// 所以一对多/多对多的循环引用问题都能解决,从任意方向开始引用的都行。 由于这种玩法似乎挤占了JsonView的原有用途,所以是有代价的,本篇讨论了代价及如何避坑。// 高级篇:模拟真实案例中JsonView的复杂关系,估计没几个人会遇到这么复杂的情况。

import com.fasterxml.jackson.annotation.JsonView

import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper

// 各种各样的 JsonView,跟数据库的View是同样用途private interface JvClientMini //给客户端的简略信息private interface JvClient : JvClientMini //给客户端的完整信息private interface JvPersist //用于数据存储

// 为了从各个方向都能随心所欲地切断循环引用,// 下边又定义了一批以JvUser和JvRole为前缀的JsonView。// 这些定义本来有可能不必要的,但这就是代价。// 不过代价倒也不算太高,毕竟输出一个个符合特定要求的Json也可能要费不少代码。private interface JvUserClientMini : JvClientMini

private interface JvUserClient : JvUserClientMini, JvClient

private interface JvUserPersist : JvPersist

private interface JvRoleClient : JvClient

private interface JvRolePersist : JvPersist

private class User(

var id: Long = 0,

var name: String = "",

@JsonView(value = [JvUserPersist::class])

var password: String = "123456",

@JsonView(value = [JvUserClient::class, JvUserPersist::class])

var roles: List = listOf()

)

private class Role(

var id: Long = 0,

var role: String = "",

@JsonView(value = [JvPersist::class])

var auth: String = "all",

@JsonView(value = [JvRoleClient::class])

var users: List = listOf()

) {

@JsonView(value = [JvClient::class])

fun usersCount() = users.size

}

private var writer = jacksonObjectMapper().writer().withDefaultPrettyPrinter()

private fun printJsonWithView(obj: Any, jv: Class) {

println("JsonView: ${jv.simpleName}");

writer.withView(jv).writeValueAsString(obj).let { println(it) }

}

fun main() {

//construct many to many reference val list = listOf(1, 2)

val users = list.map { User(it.toLong(), "name-$it") }

val roles = list.map { Role(it.toLong(), "role-$it") }

users.forEach { it.roles = roles }

roles.forEach { it.users = users }

//use @JsonView & withView(FromXXX) to resolve recursion reference println("解决json一对多&多对多循环引用问题,从任意方向开始引用的都没问题")

println("user -> roles -> users -> roles ... OK")

printJsonWithView(users[0], JvUserClientMini::class.java)

printJsonWithView(users[0], JvUserClient::class.java)

printJsonWithView(users[0], JvUserPersist::class.java)

println("role -> users -> roles -> users ... OK")

printJsonWithView(roles[0], JvRoleClient::class.java)

printJsonWithView(roles[0], JvRolePersist::class.java)

// Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: // Infinite recursion (StackOverflowError) (through reference chain: // println(writer.writeValueAsString(users[0])) // println(writer.writeValueAsString(roles[0]))

// 解决jackson循环引用问题,网上其他常见的套路: // 一对多可行,单向引用可行,多向引用比较麻烦 // @JsonBackReference // @JsonManagedReference // @JsonIdentityReference // @JsonIdentityInfo}

/* 输出结果:"""解决json一对多&多对多循环引用问题,从任意方向开始引用的都没问题user -> roles -> users -> roles ... OKJsonView: JvUserClientMini{"id" : 1,"name" : "name-1"}JsonView: JvUserClient{"id" : 1,"name" : "name-1","roles" : [ {"id" : 1,"role" : "role-1","usersCount" : 2}, {"id" : 2,"role" : "role-2","usersCount" : 2} ]}JsonView: JvUserPersist{"id" : 1,"name" : "name-1","password" : "123456","roles" : [ {"id" : 1,"role" : "role-1","auth" : "all"}, {"id" : 2,"role" : "role-2","auth" : "all"} ]}role -> users -> roles -> users ... OKJsonView: JvRoleClient{"id" : 1,"role" : "role-1","users" : [ {"id" : 1,"name" : "name-1"}, {"id" : 2,"name" : "name-2"} ],"usersCount" : 2}JsonView: JvRolePersist{"id" : 1,"role" : "role-1","auth" : "all"}"""*/

java json循环引用_填坑,解决json对象循环引用,在复杂案例中的应用相关推荐

  1. java正则匹配公司名称_【已解决】Java的正则表达式java.util.regex中的命名的组(named group)...

    [问题] 在折腾: 的过程中,需要用到命名的组,另外还用到替换中的引用命名的组. 想要搞懂如何使用. [解决过程] 1. 最开始是参考,官网手册: 中,并没有看到,如何使用命名的组. 2.参考: 得知 ...

  2. jquery java json转字符串_用jQuery以及JSON包将表单数据转为JSON字符串

    用jQuery以及JSON包将表单数据转为JSON字符串 [日期:2013-01-10] 来源:Linux社区 作者:Linux [字体:大 中 小] 提供一个将表单数据转为json对象,再转为字符串 ...

  3. byte用json存 c++_玩转golang——JSON高性能自动字段名

    前言 golang最近在中国非常火爆,尤其是后端服务开发场景.原生并发支持.优秀的性能.统一的风格,极大提升了开发效率.笔者用golang独立开发过不少小中型系统,写了几万行代码,确实很爽. 不过,统 ...

  4. java final 内存泄漏_干货详解:一文教你如何避免内部类中的内存泄漏

    我先假设读者已经熟悉在Java代码中使用嵌套类的基础知识.在本文里,我将展示嵌套类的陷阱,内部类在JVM中引起内存泄漏和内存不足错误的地方.之所以会发生这种类型的内存泄漏,是因为内部类必须始终能够访问 ...

  5. python for循环求和_怎么在python中用for循环求和

    怎么在python中用for循环求和 发布时间:2020-07-14 11:46:18 来源:亿速云 阅读:180 怎么在python中用for循环求和?相信很多没有经验的人对此束手无策,为此本文总结 ...

  6. c语言双重for循环流程图_第九章、C语言循环之for

    上一章我们讲了while和do...while循环,这一章我们来学习一下C语言中的另外一种循环结构:for循环. 我们先来看一下for循环的结构: for(expression1:expression ...

  7. 条件语句和循环语句_总结一下条件语句和循环语句

    讲了那么多的数学知识,今天我们来总结一下程序设计中的条件和循环语句.//为了方便理解,这里把所有BOOL型称为判断语句. 条件语句: 1.条件运算符和条件表达式: 表达式1?表达式2:表达式3: // ...

  8. java dcompiler 破解,小编教你解决win7系统玩鬼泣5提示计算机中DCOMPILeR_43.dll的恢复方案...

    win7旗舰版是用户量最大的一款操作系统:有不少人在使用中都遇见了win7系统玩鬼泣5提示计算机中DCOMPILeR_43.dll的问题,一般情况首次碰到win7系统玩鬼泣5提示计算机中DCOMPIL ...

  9. java 集合自定义元素_java集合 collection-list-ArrayList 将自定义对象作为元素存到ArrayList集合中,并去除重复元素。...

    import java.util.*;/*将自定义对象作为元素存到ArrayList集合中,并去除重复元素. 比如:存人对象.同姓名同年龄,视为同一个人.为重复元素. 思路: 1,对人描述,将数据封装 ...

最新文章

  1. 神经符号系统、因果推理、跨学科交互,李飞飞、Judea Pearl等16名学者共同探讨AI未来...
  2. MIT造了个“小盒子”,可以无线监测新冠患者症状,斯隆奖获得者班底打造
  3. https 不会被中间人攻击——因为中间人即使拿到了数据,也是加密的
  4. python类常用装饰器
  5. mysql 传统数据恢复_mysql 数据恢复实例
  6. linux7 共享盘创建,使用CentOS7建立samba文件共享服务器
  7. HDFS 入门和基本操作
  8. android学习笔记---android常用的软件布局方式,使用方法总结
  9. 最常用的css垂直居中方法
  10. HTML——校友会(bootstrap)
  11. Linux入门-网络实验3.3
  12. Single Number 只出现一次的数字 python实现 - ...
  13. mysql查询本年的函数_sql 查询本年、本月、本日记录的语句,附SQL日期函数
  14. html li 点图片,html中ul li前面小黑点样式 ul li一些样式
  15. XP系统开机显示“NTDETECT失败”
  16. 数字信号处理公式变程序(四)——巴特沃斯滤波器(下)
  17. ride运行时报错ERROR
  18. MPC5748G开发笔记-----MPC5748G程序跑飞uSDHCDriverIRQHandler
  19. lwip【4】 lwIP配置文件opt.h和lwipopts.h初步分析之一
  20. 【Labview】对连续采集数据的一种采样方法

热门文章

  1. 产品经理应该坚持还是妥协
  2. goodsync文件服务器,GoodSync Enterprise Server Windows服务器版
  3. dns协议类漏洞学习--结合snort分析(二)
  4. 关于virtualbox虚拟机安装Ubuntu异常处理:FATAL: NO bootable medium found! System halted
  5. TXT文本大数据比较导出工具
  6. AOP面向切面编程在Android开发中的应用
  7. Win7系统如何设置空密码远程登录
  8. 用css做一个移动射击动画,如何使用纯CSS实现一只移动的小白兔动画效果
  9. unity 打包后无法启动 steam vr
  10. 小米汽车已上路?真TM快啊。。