使用JAXB和Jackson从XSD生成JSON模式

在本文中,我演示了一种从XML Schema (XSD)生成JSON Schema的 方法 。 在概述从XML Schema创建JSON Schema的方法的同时,本文还演示了JAXB实现的用法(与JDK 9捆绑在一起的xjc版本2.2.12-b150331.1824 [build 1.9.0-ea-b68])和JSON / Java绑定实现的说明( 杰克逊 2.5.4)。

从XSD生成JSON模式的这种方法的步骤可以概括为:

  1. 应用JAXB的xjc编译器从XML Schema(XSD)生成Java类。
  2. 应用Jackson来从JAXB生成的Java类生成JSON模式。

使用JAXB的xjc从XSD生成Java类

为了便于讨论,我将使用我先前的博客文章A JAXB Nuance:字符串与枚举受限XSD字符串中的枚举使用的简单Food.xsd 。 为了方便起见,我在此处重现了该简单模式,但没有特定于先前博客文章的XML注释:

Food.xsd

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"xmlns:dustin="http://marxsoftware.blogspot.com/foodxml"targetNamespace="http://marxsoftware.blogspot.com/foodxml"elementFormDefault="qualified"attributeFormDefault="unqualified"><xs:element name="Food"><xs:complexType><xs:sequence><xs:element name="Vegetable" type="dustin:Vegetable" /><xs:element ref="dustin:Fruit" /><xs:element name="Dessert" type="dustin:Dessert" /></xs:sequence></xs:complexType></xs:element><xs:simpleType name="Vegetable"><xs:restriction base="xs:string"><xs:enumeration value="Carrot"/><xs:enumeration value="Squash"/><xs:enumeration value="Spinach"/><xs:enumeration value="Celery"/></xs:restriction></xs:simpleType><xs:element name="Fruit"><xs:simpleType><xs:restriction base="xs:string"><xs:enumeration value="Watermelon"/><xs:enumeration value="Apple"/><xs:enumeration value="Orange"/><xs:enumeration value="Grape"/></xs:restriction></xs:simpleType></xs:element><xs:simpleType name="Dessert"><xs:restriction base="xs:string"><xs:enumeration value="Pie"/><xs:enumeration value="Cake"/><xs:enumeration value="Ice Cream"/></xs:restriction></xs:simpleType></xs:schema>

使用JDK提供的JAXB实现提供的xjc命令行工具很容易生成与此XSD对应的Java类。 下一个屏幕快照使用以下命令显示了此过程:

xjc -d jaxb。\ Food.xsd

生成JavaObjectsFromFoodXsdWithXjc

这个简单的命令生成与提供的Food.xsd相对应的Java类,并将这些类放置在指定的“ jaxb”子目录中。

用Jackson从JAXB生成的类生成JSON

使用现在可用的JAXB生成的类,可以将Jackson应用于这些类以从Java类生成JSON。 杰克逊在其主门户页面上被描述为“一个用于处理的多功能Java库”,“受到Java平台可用的XML工具的质量和多样性的启发。” Jackson的存在以及类似的框架和库似乎是Oracle从Java SE 9中 删除 JEP 198 (“轻型JSON API”)的原因之一。 [值得注意的是, Java EE 7已经通过其JSR 353 (“与JSON处理有关的Java API”)的实现实现了内置的JSON支持 ,而该JSR 353与JEP 198无关。)

将Jackson应用于从我们的JAXB生成的Java类生成JSON的第一步就是获取并配置Jackson的ObjectMapper类的实例。 下一个代码清单显示了实现此目的的一种方法。

获取和配置用于JAXB序列化/反序列化的Jackson ObjectMapper

/*** Create instance of ObjectMapper with JAXB introspector* and default type factory.** @return Instance of ObjectMapper with JAXB introspector*    and default type factory.*/
private ObjectMapper createJaxbObjectMapper()
{final ObjectMapper mapper = new ObjectMapper();final TypeFactory typeFactory = TypeFactory.defaultInstance();final AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(typeFactory);// make deserializer use JAXB annotations (only)mapper.getDeserializationConfig().with(introspector);// make serializer use JAXB annotations (only)mapper.getSerializationConfig().with(introspector);return mapper;
}

上面的代码清单演示了如何获取Jackson的ObjectMapper实例并将其配置为使用默认类型的工厂和面向JAXB的注释自检器。

在实例化并正确配置了Jackson ObjectMapper情况下,很容易使用该ObjectMapper实例从生成的JAXB类生成JSON。 下一个代码清单中演示了使用不推荐使用的Jackson类JsonSchema实现此目的的一种方法。

使用不推荐使用的com.fasterxml.jackson.databind.jsonschema.JsonSchema类从Java类生成JSON

/*** Write JSON Schema to standard output based upon Java source* code in class whose fully qualified package and class name* have been provided.** @param mapper Instance of ObjectMapper from which to*     invoke JSON schema generation.* @param fullyQualifiedClassName Name of Java class upon*    which JSON Schema will be extracted.*/
private void writeToStandardOutputWithDeprecatedJsonSchema(final ObjectMapper mapper, final String fullyQualifiedClassName)
{try{final JsonSchema jsonSchema = mapper.generateJsonSchema(Class.forName(fullyQualifiedClassName));out.println(jsonSchema);}catch (ClassNotFoundException cnfEx){err.println("Unable to find class " + fullyQualifiedClassName);}catch (JsonMappingException jsonEx){err.println("Unable to map JSON: " + jsonEx);}
}

上面清单中的代码实例化获取提供的Java类的类定义(在我的示例中由JAXB xjc编译器生成的最高级别的Food类),并将对该JAXB生成的类的引用传递给ObjectMapper的generateJsonSchema(Class < ?>)方法。 不推荐使用的JsonSchema类的toString()实现非常有用,并且可以轻松写出从JAXB生成的类生成的JSON。

为了进行演示,我将演示驱动程序作为main(String [])函数提供。 在下一个代码清单中提供了该函数以及到目前为止的整个类(包括上面显示的方法)。

JsonGenerationFromJaxbClasses.java,版本1

package dustin.examples.jackson;import com.fasterxml.jackson.databind.AnnotationIntrospector;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector;import com.fasterxml.jackson.databind.jsonschema.JsonSchema;import static java.lang.System.out;
import static java.lang.System.err;/*** Generates JavaScript Object Notation (JSON) from Java classes* with Java API for XML Binding (JAXB) annotations.*/
public class JsonGenerationFromJaxbClasses
{/*** Create instance of ObjectMapper with JAXB introspector* and default type factory.** @return Instance of ObjectMapper with JAXB introspector*    and default type factory.*/private ObjectMapper createJaxbObjectMapper(){final ObjectMapper mapper = new ObjectMapper();final TypeFactory typeFactory = TypeFactory.defaultInstance();final AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(typeFactory);// make deserializer use JAXB annotations (only)mapper.getDeserializationConfig().with(introspector);// make serializer use JAXB annotations (only)mapper.getSerializationConfig().with(introspector);return mapper;}/*** Write out JSON Schema based upon Java source code in* class whose fully qualified package and class name have* been provided.** @param mapper Instance of ObjectMapper from which to*     invoke JSON schema generation.* @param fullyQualifiedClassName Name of Java class upon*    which JSON Schema will be extracted.*/private void writeToStandardOutputWithDeprecatedJsonSchema(final ObjectMapper mapper, final String fullyQualifiedClassName){try{final JsonSchema jsonSchema = mapper.generateJsonSchema(Class.forName(fullyQualifiedClassName));out.println(jsonSchema);}catch (ClassNotFoundException cnfEx){err.println("Unable to find class " + fullyQualifiedClassName);}catch (JsonMappingException jsonEx){err.println("Unable to map JSON: " + jsonEx);}}/*** Accepts the fully qualified (full package) name of a* Java class with JAXB annotations that will be used to* generate a JSON schema.** @param arguments One argument expected: fully qualified*     package and class name of Java class with JAXB*     annotations.*/public static void main(final String[] arguments){if (arguments.length < 1){err.println("Need to provide the fully qualified name of the highest-level Java class with JAXB annotations.");System.exit(-1);}final JsonGenerationFromJaxbClasses instance = new JsonGenerationFromJaxbClasses();final String fullyQualifiedClassName = arguments[0];final ObjectMapper objectMapper = instance.createJaxbObjectMapper();instance.writeToStandardOutputWithDeprecatedJsonSchema(objectMapper, fullyQualifiedClassName);}
}

要针对基于Food.xsd的JAXB的xjc生成的Java类运行此相对通用的代码,我需要提供最高级别生成的类的标准软件包名称和类名称。 在这种情况下,这就是com.blogspot.marxsoftware.foodxml.Food (程序包名称基于XSD的名称空间,因为在运行xjc时我没有明确覆盖它)。 当我使用完全限定的类名以及类路径上的JAXB类和Jackson库运行上述代码时,我看到以下JSON写入了标准输出。

生成的JSON

{"type":"object","properties":{"vegetable":{"type":"string","enum":["CARROT","SQUASH","SPINACH","CELERY"]},"fruit":{"type":"string"},"dessert":{"type":"string","enum":["PIE","CAKE","ICE_CREAM"]}}}

人类(包括许多开发人员)比打印的JSON更喜欢漂亮的打印 。 我们可以调整演示类的方法writeToStandardOutputWithDeprecatedJsonSchema(ObjectMapper, String) ,如下所示,以写出缩进的JSON ,以更好地反映其层次结构性质。 接下来显示此修改的方法。

修改了writeToStandardOutputWithDeprecatedJsonSchema(ObjectMapper,String)以写入缩进的JSON

/*** Write out indented JSON Schema based upon Java source* code in class whose fully qualified package and class* name have been provided.** @param mapper Instance of ObjectMapper from which to*     invoke JSON schema generation.* @param fullyQualifiedClassName Name of Java class upon*    which JSON Schema will be extracted.*/
private void writeToStandardOutputWithDeprecatedJsonSchema(final ObjectMapper mapper, final String fullyQualifiedClassName)
{try{final JsonSchema jsonSchema = mapper.generateJsonSchema(Class.forName(fullyQualifiedClassName));out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonSchema));}catch (ClassNotFoundException cnfEx){err.println("Unable to find class " + fullyQualifiedClassName);}catch (JsonMappingException jsonEx){err.println("Unable to map JSON: " + jsonEx);}catch (JsonProcessingException jsonEx){err.println("Unable to process JSON: " + jsonEx);}
}

当我使用此修改后的方法再次运行演示类时,JSON输出在美学上更加令人愉悦:

生成带有缩进通信层次结构的JSON

{"type" : "object","properties" : {"vegetable" : {"type" : "string","enum" : [ "CARROT", "SQUASH", "SPINACH", "CELERY" ]},"fruit" : {"type" : "string"},"dessert" : {"type" : "string","enum" : [ "PIE", "CAKE", "ICE_CREAM" ]}}
}

我在这篇文章中一直在使用Jackson 2.5.4。 com.fasterxml.jackson. databind .jsonschema.JsonSchemacom.fasterxml.jackson. databind .jsonschema.JsonSchema 该版本不建议使用com.fasterxml.jackson. databind .jsonschema.JsonSchema ,并带有以下注释:“从2.2开始,我们建议使用外部JSON Schema生成器模块 。” 鉴于此,我现在看一下使用新的首选方法( Jackson JSON Schema Module方法)。

最显著的变化是使用JsonSchema在类com.fasterxml.jackson.module.jsonSchema包,而不是使用JsonSchema在类com.fasterxml.jackson.databind.jsonschema包。 获取这些不同版本的JsonSchema类的实例的方法也不同。 下一个代码清单演示了如何使用更新的首选方法从Java类生成JSON。

使用Jackson的更新和首选com.fasterxml.jackson.module.jsonSchema.JsonSchema

/*** Write out JSON Schema based upon Java source code in* class whose fully qualified package and class name have* been provided. This method uses the newer module JsonSchema* class that replaces the deprecated databind JsonSchema.** @param fullyQualifiedClassName Name of Java class upon*    which JSON Schema will be extracted.*/
private void writeToStandardOutputWithModuleJsonSchema(final String fullyQualifiedClassName)
{final SchemaFactoryWrapper visitor = new SchemaFactoryWrapper();final ObjectMapper mapper = new ObjectMapper();try{mapper.acceptJsonFormatVisitor(mapper.constructType(Class.forName(fullyQualifiedClassName)), visitor);final com.fasterxml.jackson.module.jsonSchema.JsonSchema jsonSchema = visitor.finalSchema();out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonSchema));}catch (ClassNotFoundException cnfEx){err.println("Unable to find class " + fullyQualifiedClassName);}catch (JsonMappingException jsonEx){err.println("Unable to map JSON: " + jsonEx);}catch (JsonProcessingException jsonEx){err.println("Unable to process JSON: " + jsonEx);}
}

下表将两个Jackson JsonSchema类的用法与左侧较早显示的已弃用方法进行了比较(为该比较进行了一些调整),并在右侧推荐了较新的方法。 两者针对要从其编写JSON的相同给定Java类生成相同的输出。

/*** Write out JSON Schema based upon Java source code in* class whose fully qualified package and class name have* been provided. This method uses the deprecated JsonSchema* class in the "databind.jsonschema" package* {@see com.fasterxml.jackson.databind.jsonschema}.** @param fullyQualifiedClassName Name of Java class upon*    which JSON Schema will be extracted.*/
private void writeToStandardOutputWithDeprecatedDatabindJsonSchema(final String fullyQualifiedClassName)
{final ObjectMapper mapper = new ObjectMapper();try{final com.fasterxml.jackson.databind.jsonschema.JsonSchema jsonSchema =mapper.generateJsonSchema(Class.forName(fullyQualifiedClassName));out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonSchema));}catch (ClassNotFoundException cnfEx){err.println("Unable to find class " + fullyQualifiedClassName);}catch (JsonMappingException jsonEx){err.println("Unable to map JSON: " + jsonEx);}catch (JsonProcessingException jsonEx){err.println("Unable to process JSON: " + jsonEx);}
}
/*** Write out JSON Schema based upon Java source code in* class whose fully qualified package and class name have* been provided. This method uses the newer module JsonSchema* class that replaces the deprecated databind JsonSchema.** @param fullyQualifiedClassName Name of Java class upon*    which JSON Schema will be extracted.*/
private void writeToStandardOutputWithModuleJsonSchema(final String fullyQualifiedClassName)
{final SchemaFactoryWrapper visitor = new SchemaFactoryWrapper();final ObjectMapper mapper = new ObjectMapper();try{mapper.acceptJsonFormatVisitor(mapper.constructType(Class.forName(fullyQualifiedClassName)), visitor);final com.fasterxml.jackson.module.jsonSchema.JsonSchema jsonSchema = visitor.finalSchema();out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonSchema));}catch (ClassNotFoundException cnfEx){err.println("Unable to find class " + fullyQualifiedClassName);}catch (JsonMappingException jsonEx){err.println("Unable to map JSON: " + jsonEx);}catch (JsonProcessingException jsonEx){err.println("Unable to process JSON: " + jsonEx);}
}

这篇博客文章展示了两种方法,这些方法使用由Jackson提供的名称为JsonSchema的类的不同版本来基于从具有JAXB的xjc的XSD生成的Java类编写JSON。 本文中演示的整个过程是一种从XML Schema生成JSON Schema的方法。

翻译自: https://www.javacodegeeks.com/2015/06/generating-json-schema-from-xsd-with-jaxb-and-jackson.html

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Integration完整示例

本文是我们名为“ Spring Integration for EAI ”的学院课程的一部分。 在本课程中&#xff0c;向您介绍了企业应用程序集成模式以及Spring Integration如何解决它们。 接下来&#xff0c;您将深入研究Spring Integration的基础知识&#xff0c;例如通道&#xff0c;转换器和适…

配置环境_JavaJDK环境变量配置

1.Java环境搭建1.1 JDK与JREJDK(Java Development Kit Java开发工具包)JDK是提供给Java开发人员使用的&#xff0c;其中包含了java的开发工具&#xff0c;也包括了JRE。所以安装了JDK&#xff0c;就不用在单独安装JRE了。其中开发工具&#xff1a;编译工具(javac.exe)打包工具(…

僵固式思维 OR 成长式思维

有意无意中&#xff0c;看到这样的一篇文章&#xff0c;觉得非常富有正能量&#xff0c;而且也比较有同感。而且&#xff0c;不仅仅对于职场暂时失落或者失意的人有帮助&#xff0c;就是对学生&#xff0c;也一样的。故特分享&#xff0c;以共勉之。 我想每个新人进入职场之后都…

Asp.net MVC 的一些总结(二)——图片显示

这里实现的是&#xff0c;如下图片所示的效果&#xff1a; 当然&#xff0c;当你看的下图的时候&#xff0c;请不要自己想当然的认为是简单的html布局&#xff01;&#xff01;&#xff01; &#xff08;1&#xff09;业务说明&#xff1a;图片地址是数据库里存的&#xff0c;图…

Spring整合基础

本文是我们名为“ Spring Integration for EAI ”的学院课程的一部分。 在本课程中&#xff0c;向您介绍了企业应用程序集成模式以及Spring Integration如何解决它们。 接下来&#xff0c;您将深入研究Spring Integration的基础知识&#xff0c;例如通道&#xff0c;转换器和适…

java 布局管理器_有时在Java中,一个布局管理器是不够的

java 布局管理器在开发Java Swing应用程序时&#xff0c;最经常的是&#xff0c;我们需要在多个嵌套面板中使用多个布局管理器。 这通常不是问题&#xff0c;被认为是几乎所有人类已知语言的所有UI开发的常规做法。 但是&#xff0c;大多数情况下&#xff0c;对于UI中的每个面板…

支付宝支付、微信支付(最详细教程)

对接支付宝支付接口&#xff0c;官方文档已经写的很清楚了&#xff0c;但是也有很多像我一样的小白&#xff0c;第一次对接支付宝支付接口&#xff0c;会有些迷茫&#xff0c;所以我在此写下这篇文章&#xff0c;给我和我一样的同学&#xff0c;一点思路吧。 第一步&#xff1…

降雨插值_ArcGIS计算土壤侵蚀模数(二)降雨侵蚀力因子R计算

本次采用中国土壤流失方程CSLE计算土壤侵蚀模数&#xff0c;计算公式为&#xff1a;ARKLSBET式中&#xff0c;式中&#xff1a;A—土壤侵蚀模数。thm-2a-1&#xff1b;R—降雨侵蚀力因子&#xff0c;MJmmhm-2h-1a-1&#xff1b;K—土壤可蚀性因子&#xff0c;thm2hhm-2MJmm-1&a…

购买阿里云ECS服务器忘记终端管理密码或者没有设置

自己开发一个APP,想把源码放到服务器上跑一跑,发现使用Xshell远程连接不上去,我记得买服务器的时候没有设置。 一般有两种方法: 1.买服务器的时候,阿里会给你发一份邮件,邮件里面有,这个是官方的说法,我是公司CTO,账号是老板开的,根本不可能看到邮件,所以对我来说不…

输出空格隔开换行_【前端干货】CSS 的空格处理

一空格规则HTML 代码的空格通常会被浏览器忽略。<p>◡◡hello◡◡world◡◡</p>上面是一行 HTML 代码&#xff0c;文字的前部、内部和后部各有两个空格。为了便于识别&#xff0c;这里使用半圆形符号◡表示空格。浏览器的输出结果如下。hello world可以看到&#x…

宝塔面板绑定域名导致无法访问

用这个命令rm -f /www/server/panel/data/domain.conf删除绑定域名后&#xff0c; 就能用ip端口进入面板了&#xff0c;以后还是不要绑定域名了 主要是因为我手残。 看重点&#xff0c;我是绑定了域名&#xff0c;用域名也无法访问。 现在终于进去啦

宝塔访问域名访问不到

首先说明一点&#xff0c;我这个问题不是宝塔面板绑定域名的那种情况。 浏览器输入域名会报上面的错误&#xff0c;经过各种尝试&#xff0c;发现是安全组没有放开&#xff0c;在阿里云控制台添加一个80/80的通用安全组规则即可&#xff0c;知道上行和下行的区别&#xff0c;打…

双千兆和双频千兆哪个好_关于千兆路由器的那些事儿!赶紧收藏

无线Wi-Fi已成为现代人生活、工作的标配&#xff0c;随着百兆乃至千兆的光纤网络普及&#xff0c;传统路由器已跟不上时代的速度了。不少用户的眼光已投向速度更快的千兆路由器&#xff0c;那么大家真的了解什么是千兆路由器吗&#xff1f;千兆路由器有哪几种&#xff1f;近期火…

华三ospf联动bfd_HCIE2020__路由交换专家__BFD综合实验

1.1.1 关于本实验本实验通过配置BFD与BGP协议联动及与VRRP协议联动&#xff0c;掌握BFD的功能和配置方法。1.1.2 实验目的理解BFD的工作原理。 掌握BFD与BGP联动的应用场景及配置方法。 掌握BFD与VRRP联动的应用场景及配置方法。1.1.3 实验组网介绍图1-1 BFD原理配置实验拓扑图…

大学生助学贷款如何还利息(本金+利息都可以)

生源地助学贷款还利息的步骤: 1、首先需要将钱转入支付宝,金额稍微高于应还款项即可。然后登陆电脑版支付宝,一定是要电脑登陆(手机上无法操作),如图所示 2、然后在支付宝主页中,点击右上角的“应用中心”,然后点击“生活服务”如图所示。

谷歌浏览器下载的内容老是自动打开

原因是每次下载内容在浏览器左下角都有提示&#xff0c;一般都是选择打开所在文件夹&#xff0c;一次手残&#xff0c;点了总是打开此文件导致一下载文件就自动打开。 解决方法。 1.点击右上角的... 2.找到设置-高级设置-下载 3.关掉我标红的位置信息即可。现在看不到啦&…

JBoss Fuse 6.2发布–指导如何快速尝试

在上周的红帽峰会上&#xff0c;宣布发布了JBoss Fuse 6.2 。 我要祝贺保险丝团队发布此版本。 我知道他们今年以来一直非常努力地进行质量检查&#xff0c;并确保质量检查通过了企业产品所期望的高品质壁垒。 因此&#xff0c;带着我的Camel帽子&#xff0c;很高兴看到包含最…

插入文件找不到桌面了?

解决方法&#xff0c;在那个界面空白处&#xff0c;右键显示所有文件即可。

mysql自增长主键_MySQL数据库8(九)列属性之主键、自增长

主键顾名思义&#xff0c;主要的键&#xff0c;primary key&#xff0c;在一张表中&#xff0c;有且只有一个字段&#xff0c;里面的值具有唯一性创建主键随表创建系统提供了两种增加主键的方式&#xff1a;1、直接在需要当做主键的字段之后&#xff0c;增加primary key属性来确…

初学者如何学编程呢

先简单做个测试,这样就能找出你比较适合哪种语言。 下面简单介绍一下不同的语言吧