Jackson标签的高阶使用样例--多继承/子类、对象id、JsonIdentityInfo、JsonTypeInfo、JsonSubTypes

这篇具有很好参考价值的文章主要介绍了Jackson标签的高阶使用样例--多继承/子类、对象id、JsonIdentityInfo、JsonTypeInfo、JsonSubTypes。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 背景

最近笔者在开发大数据平台XSailboat数据资产目录 模块。它的其中一个功能是能定义并查看资产数据。我们支持的资产类型不仅有关系数据库表,也支持Kafka主题,hdfs上的文件等。对于Kafka主题,hdfs文件等,它们没有强模式约束和描述,但为了理解、查看和约束其中的结构化数据,我们支持在这类资产上附加上模式定义的功能。

对于模式的描述/模型,我参考了JsonSchema,OpenAPI 3.0的Schema,最终决定自己定义模式结构。这种模式结构能扩展、能转换成那些标准模式,为后续扩展和适应性调整留余地。

我期望的模式结构,举例:

{
	"type":"object" ,
	"fields":[{
		"name" : "f0" ,
		"description" : "字段0的描述信息" ,
		"dataType" : "string"
 	} ,
 	{
 		"name" : "f1" ,
 		"description" : "字段1的描述信息" ,
 		"dataType" : {
 			"type" : "array" ,
 			"itemType" : "string"
 		}
 	} ,
 	....
 	]
}

这里我对数据类型进行了抽闲,它可以是,
基本类型:

  • string
  • double
  • long
  • int
  • bool
  • datetime

扩展类型

  • object
  • array

基本类型在我们的Java Bean定义中,它是一个类型为BaseType的JavaBean,不是字符串,所以如何序列化成JSON时,得到

{
...
	"dataType" : "string" ,
...
}

的效果,而不是,

...
	"dataType" : ["BaseType" , "string"]
或者
	"dataType" : {
		"type" : "string"
	}
...

笔者经过尝试,使用了@JsonIdentityInfo和@JsonIdentityReference解决这个问题文章来源地址https://www.toymoban.com/news/detail-801706.html

2. 代码

  • com.cimstech.sailboat.common.schema.Type
package com.cimstech.sailboat.common.schema;

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(
	    use = JsonTypeInfo.Id.NAME, // Were binding by providing a name
	    include = JsonTypeInfo.As.PROPERTY, // The name is provided in a property
	    property = "type", // Property name is type
	    visible = true // Retain the value of type after deserialisation
	    , defaultImpl = BaseType.class	// 如果不是下面指定的那两种,就缺省认定它是BaseType类型的,走它的反序列化逻辑。
	)
@JsonSubTypes({//Below, we define the names and the binding classes.
    @JsonSubTypes.Type(value = ArrayType.class, name = "array") ,
    @JsonSubTypes.Type(value = ObjectType.class, name = "object")
})
public interface Type
{
}
  • com.cimstech.sailboat.common.schema.BaseType
package com.cimstech.sailboat.common.schema;

import com.cimstech.xfront.common.reflect.XClassUtil;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIdentityReference;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;

import lombok.Data;

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class , property = "name"
		, resolver = BaseTypeIdResolver.class , scope = BaseType.class)			// 用name来做id
@JsonIdentityReference(alwaysAsId = true)		// 总是使用Id来代表这个类的对象
@Data
public class BaseType implements Type
{
	public static BaseType STRING = new BaseType(XClassUtil.sCSN_String) ;
	public static BaseType LONG = new BaseType(XClassUtil.sCSN_Long) ;
	public static BaseType DOUBLE = new BaseType(XClassUtil.sCSN_Double) ;
	public static BaseType INTEGER = new BaseType(XClassUtil.sCSN_Integer) ;
	public static BaseType BOOLEAN = new BaseType(XClassUtil.sCSN_Bool) ;
	public static BaseType DATETIME = new BaseType(XClassUtil.sCSN_DateTime) ;
	
	public static BaseType of(String aTypeName)
	{
		switch(aTypeName)
		{
		case XClassUtil.sCSN_String:
			return STRING ;
		case XClassUtil.sCSN_Long:
			return LONG ;
		case XClassUtil.sCSN_Double:
			return DOUBLE ;
		case XClassUtil.sCSN_Integer:
			return INTEGER ;
		case XClassUtil.sCSN_Bool:
			return BOOLEAN ;
		case XClassUtil.sCSN_DateTime:
			return DATETIME ;
		default:
			throw new IllegalArgumentException("未知的基本类型:"+aTypeName) ;
		}
	}
	
	final String name ;
	
	private BaseType(String aName)
	{
		name = aName ;
	}
	
	@Override
	public String toString()
	{
		return name ;
	}
}
  • com.cimstech.sailboat.common.schema.ArrayType
package com.cimstech.sailboat.common.schema;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ArrayType implements Type
{
	/**
	 * 数组的元素类型
	 */
	Type itemType ;
}
  • com.cimstech.sailboat.common.schema.ObjectType
package com.cimstech.sailboat.common.schema;

import java.util.List;

import lombok.Data;

@Data
public class ObjectType implements Type
{
	/**
	 * 字段
	 */
	List<Field> fields ;
}

  • com.cimstech.sailboat.common.schema.Field
package com.cimstech.sailboat.common.schema;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Field
{
	String name ;
	
	String description ;
	
	Type dataType ;
}

  • com.cimstech.sailboat.common.schema.BaseTypeIdResolver
package com.cimstech.sailboat.common.schema;

import com.fasterxml.jackson.annotation.ObjectIdGenerator.IdKey;
import com.fasterxml.jackson.annotation.ObjectIdResolver;

public class BaseTypeIdResolver implements ObjectIdResolver
{
	
	@Override
	public void bindItem(IdKey aId, Object aPojo)
	{
	}

	@Override
	public Object resolveId(IdKey aId)
	{
		return BaseType.of(aId.key.toString()) ;
	}

	@Override
	public ObjectIdResolver newForDeserialization(Object aContext)
	{
		return this ;
	}

	@Override
	public boolean canUseFor(ObjectIdResolver aResolverType)
	{
		return aResolverType.getClass() == getClass() ;
	}

}

到了这里,关于Jackson标签的高阶使用样例--多继承/子类、对象id、JsonIdentityInfo、JsonTypeInfo、JsonSubTypes的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python 继承和子类示例:从 Person 到 Student 的演示

    继承允许我们定义一个类,该类继承另一个类的所有方法和属性。父类是被继承的类,也叫做基类。子类是从另一个类继承的类,也叫做派生类。 任何类都可以成为父类,因此语法与创建任何其他类相同: 示例,创建一个名为 Person 的类,具有 firstname 和 lastname 属性以及一个

    2024年02月08日
    浏览(24)
  • java子类继承父类方法、或者接口中方法的javadoc注释

    详情可以阅读: https://docs.oracle.com/en/java/javase/19/docs/specs/javadoc/doc-comment-spec.html#method-comment-inheritance 子类继承父类、或者子类实现接口,在子类中为了避免重复写注释,可以在子类方法注释的主要描述部分、或者@return、@param、@throws标记后面的文本参数部分插入{@inheritDoc}标记

    2024年02月11日
    浏览(31)
  • 我在VScode学Java继承(Java继承的特点、super关键字、super和this对比、方法重写、子类构造器)贰

    类的成员包括:成员变量;成员方法;构造方法 构造方法:不管什么修饰符都不可继承 成员变量:都可以继承,但注意一点(继承!=调用,私有的就不可调用) 成员方法:非私有可以。私有不可。 我的个人博客主页:如果’\\\'真能转义1️⃣说1️⃣的博客主页 关于Java基本语

    2024年02月14日
    浏览(37)
  • 【C++】 为什么多继承子类重写的父类的虚函数地址不同?『 多态调用汇编剖析』

    👀 樊梓慕: 个人主页  🎥 个人专栏: 《C语言》 《数据结构》 《蓝桥杯试题》 《LeetCode刷题笔记》 《实训项目》 《C++》 《Linux》《算法》 🌝 每一个不曾起舞的日子,都是对生命的辜负 本篇文章主要是为了解答有关多态的那篇文章那块的一个奇怪现象,大家还记得这张

    2024年02月19日
    浏览(27)
  • C# 父类实现的 IEquatable<T> 接口,重写的相等性判断函数都能被子类继承

    在父类重写的 Equals 方法,继承的 IEquatable 接口,重写的 == ,!= 运算符,重写的 GetHashCode 方法在子类中仍然是表现为被重写的状态。 现在让子类也实现 IEquatable 接口 此时代码提示如下 子类实现接口后,调用的默认就是子类实现的 Equals 方法。也可以用强制转换调用父类的

    2024年02月16日
    浏览(33)
  • 链式-父类中返回子类对象

    一晃五年没写博客了,依旧再C#上耕耘,依旧没有啥建树,现在也不知道.net上还有多少人再使用,在这里分享一些自己觉得写的还算优雅的代码。 对于自己写着完的代码,我特别喜欢链式(来源于jQuery的影响吧),大部分时候链式就是将返回值为void类型的对象,返回this指针

    2024年02月05日
    浏览(26)
  • 5.4 如何在Mybatis中使用insert标签并返回主键id?-- 教你通用做法

    通过 《上文》,我们学会了XML映射文件Mapper的创建,以及最常用的select标签和resultMap标签,本文主要讲解 insert标签 ,用于和insert SQL语句映射,非常简单上手,只有两个点可以扩展讲讲:一个点是 insert后返回主键id(会介绍两种方式) ,另外一个点是 实现批量添加 ,原本打算

    2024年02月06日
    浏览(31)
  • 【C/C++】父类指针指向子类对象 | 隐藏

    创作不易,本篇文章如果帮助到了你,还请点赞 关注支持一下♡𖥦)!! 主页专栏有更多知识,如有疑问欢迎大家指正讨论,共同进步! 🔥c++系列专栏:C/C++零基础到精通 🔥 给大家跳段街舞感谢支持!ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ c语言内容💖:

    2024年02月11日
    浏览(32)
  • C++之模板类指向子类对象(一百四十六)

    简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏: Audio工程师进阶系列 【 原创干货持续更新中…… 】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:An

    2024年02月12日
    浏览(47)
  • Python 常用内置函数详解(一):isinstance()函数----判断对象是否是类或子类

    isinstance() 函数用于判断对象是否是类或者类型元组中任意类元素的实例。 语法结构如下: 【示例1】使用isinstance()函数判断一个实例对象是否属于某个类。代码如下: 程序运行结果如下图所示: 【示例2】使用isinstance()函数判断某个对象是否属于原生类型,代码如下: 程序

    2024年02月22日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包