除Swagger等文档插件,全网首发,同时支持Json和Xml
核心工具类
Json2Utils.java
package com.xxx.demo.common.util;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.NullNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.ser.XmlSerializerProvider;
import com.fasterxml.jackson.dataformat.xml.util.XmlRootNameLookup;
import com.kjetland.jackson.jsonSchema.JsonSchemaConfig;
import com.kjetland.jackson.jsonSchema.JsonSchemaGenerator;
public final class Json2Utils {
//数组或List的循环次数
private static final int ARRAY_LOOP = 1;
//Map的循环次数
private static final int MAP_LOOP = 1;
//Map的key的前缀
private static final String MAP_KEY_PREFIX = "KEY_";
private static final ObjectMapper innerMapper = new ObjectMapper();
private static final XmlSerializerProvider provider = new XmlSerializerProvider(new XmlRootNameLookup());
static {
provider.setNullValueSerializer(new JsonSerializer<Object> () {
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers)
throws IOException {
gen.writeString("");
}
});
}
public static <T> String clazz2Json(ObjectMapper mapper, Class<T> clazz) {
JavaType javaType = mapper.getTypeFactory().constructType(clazz);
return javaType2Json(mapper, javaType);
}
public static <T> String clazz2Json(ObjectMapper mapper, TypeReference<T> reference) {
JavaType javaType = mapper.getTypeFactory().constructType(reference);
return javaType2Json(mapper, javaType);
}
private static String javaType2Json(ObjectMapper mapperSource, JavaType javaType) {
ObjectMapper mapper = mapperSource.copy();
ObjectMapper innerMapper = Json2Utils.innerMapper;
JsonSchemaConfig config = JsonSchemaConfig.vanillaJsonSchemaDraft4();
JsonSchemaGenerator schemaGenerator = new JsonSchemaGenerator(innerMapper, config);
JsonNode jsonNode = schemaGenerator.generateJsonSchema(javaType);
JsonNode normalize = normalize(innerMapper, jsonNode);
Object value = innerMapper.convertValue(normalize, javaType);
mapper.setDefaultPropertyInclusion(Include.ALWAYS);
if (mapper instanceof XmlMapper) {
mapper.setSerializerProvider(provider);
}
try {
return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(value);
} catch (JsonProcessingException e) {
return null;
}
}
private static JsonNode normalize(ObjectMapper mapper, JsonNode source) {
if (shouldArray(source)) {
ArrayNode arrayNode = mapper.createArrayNode();
fillJsonNode(mapper, source, source, arrayNode);
return arrayNode;
} else if (shouldObject(source)) {
ObjectNode objectNode = mapper.createObjectNode();
fillJsonNode(mapper, source, source, objectNode);
return objectNode;
}
return NullNode.getInstance();
}
private static void fillJsonNode(ObjectMapper mapper, JsonNode sourceRoot, JsonNode source, JsonNode target) {
if (isArray(source)) {
for (int i = 0; i < ARRAY_LOOP; i++) {
fillArrayNode(mapper, sourceRoot, source, target);
}
} else if (shouldObject(source)) {
fillObjectNode(mapper, sourceRoot, source, target);
}
}
private static void fillArrayNode(ObjectMapper mapper, JsonNode sourceRoot, JsonNode source, JsonNode target) {
JsonNode arrayItems = getArrayItems(source);
if (isArray(arrayItems)) {
ArrayNode arrayNode = mapper.createArrayNode();
((ArrayNode) target).add(arrayNode);
fillJsonNode(mapper, sourceRoot, arrayItems, arrayNode);
} else if (isMap(arrayItems)) {
JsonNode propertiesNode = arrayItems.get("additionalProperties");
if (isPojoPlain(propertiesNode)) {
ObjectNode objectNode = mapper.createObjectNode();
((ArrayNode) target).add(objectNode);
fillJsonNode(mapper, sourceRoot, arrayItems, objectNode);
} else {
((ArrayNode) target).add(NullNode.getInstance());
}
} else if (isPojoPlain(arrayItems)) {
JsonNode jsonNode = sourceRoot.at(arrayItems.get("$ref").asText().substring(1));
ObjectNode objectNode = mapper.createObjectNode();
((ArrayNode) target).add(objectNode);
fillJsonNode(mapper, sourceRoot, jsonNode, objectNode);
} else {
((ArrayNode) target).add(NullNode.getInstance());
}
}
private static void fillObjectNode(ObjectMapper mapper, JsonNode sourceRoot, JsonNode source, JsonNode target) {
if (isMap(source)) {
for (int i = 0; i < MAP_LOOP; i++) {
fillMapNode(mapper, sourceRoot, source, target, i);
}
} else if (source.has("properties")) {
Iterator<Entry<String, JsonNode>> iterator = source.get("properties").fields();
while (iterator.hasNext()) {
Map.Entry<String, JsonNode> entry = iterator.next();
JsonNode jsonNode = entry.getValue();
if (shouldArray(jsonNode)) {
ArrayNode arrayNode = mapper.createArrayNode();
((ObjectNode) target).set(entry.getKey(), arrayNode);
fillJsonNode(mapper, sourceRoot, jsonNode, arrayNode);
} else if (shouldObject(jsonNode)) {
ObjectNode objectNode = mapper.createObjectNode();
((ObjectNode) target).set(entry.getKey(), objectNode);
fillJsonNode(mapper, sourceRoot, jsonNode, objectNode);
} else {
((ObjectNode) target).set(entry.getKey(), NullNode.getInstance());
}
}
}
}
private static void fillMapNode(ObjectMapper mapper, JsonNode sourceRoot, JsonNode source, JsonNode target, int i) {
String keyName = MAP_KEY_PREFIX + i;
JsonNode propertiesNode = source.get("additionalProperties");
if (isArray(propertiesNode)) {
ArrayNode arrayNode = mapper.createArrayNode();
((ObjectNode) target).set(keyName, arrayNode);
fillJsonNode(mapper, sourceRoot, propertiesNode, arrayNode);
} else if (isMap(propertiesNode)) {
ObjectNode objectNode = mapper.createObjectNode();
((ObjectNode) target).set(keyName, objectNode);
fillJsonNode(mapper, sourceRoot, propertiesNode, objectNode);
} else if (isPojoPlain(propertiesNode)) {
JsonNode jsonNode = sourceRoot.at(propertiesNode.get("$ref").asText().substring(1));
ObjectNode objectNode = mapper.createObjectNode();
((ObjectNode) target).set(keyName, objectNode);
fillJsonNode(mapper, sourceRoot, jsonNode, objectNode);
} else {
((ObjectNode) target).set(keyName, NullNode.getInstance());
}
}
private static boolean isArray(JsonNode jsonNode) {
if (!jsonNode.has("type")) {
return false;
}
return "array".equals(jsonNode.get("type").asText());
}
private static boolean isMap(JsonNode jsonNode) {
if (!jsonNode.has("type")) {
return false;
}
return "object".equals(jsonNode.get("type").asText()) && !jsonNode.get("additionalProperties").isBoolean();
}
private static boolean isPojoRoot(JsonNode jsonNode) {
return "object".equals(jsonNode.get("type").asText()) && jsonNode.get("additionalProperties").isBoolean()
&& !Arrays.asList("Local Date Time", "Local Date", "Local Time", "Offset Date Time").contains(jsonNode.get("title").asText());
}
private static boolean isPojoPlain(JsonNode jsonNode) {
if (jsonNode.has("properties")) {
return true;
}
if (!jsonNode.has("$ref")) {
return false;
}
String ref = jsonNode.get("$ref").asText();
return !ref.endsWith("LocalDateTime") && !ref.endsWith("LocalDate") && !ref.endsWith("LocalTime") && !ref.endsWith("OffsetDateTime");
}
private static boolean shouldArray(JsonNode jsonNode) {
return isArray(jsonNode);
}
private static boolean shouldObject(JsonNode jsonNode) {
if (isMap(jsonNode)) {
return true;
}
if (jsonNode.has("title") && isPojoRoot(jsonNode)) {
return true;
}
if (!jsonNode.has("title") && isPojoPlain(jsonNode)) {
return true;
}
return false;
}
private static JsonNode getArrayItems(JsonNode source) {
return source.get("items");
}
}
怎么使用
测试用的实体类
Base.java
package com.xxx.demo.common.jsontest;
import java.util.Arrays;
public class Base<T> {
private String address;
private T[] listDt;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public T[] getListDt() {
return listDt;
}
public void setListDt(T[] listDt) {
this.listDt = listDt;
}
@Override
public String toString() {
return "Base [address=" + address + ", listDt=" + Arrays.toString(listDt) + "]";
}
}
BaseDt.java
package com.xxx.demo.common.jsontest;
import java.math.BigInteger;
import java.time.LocalDate;
import java.util.Date;
import java.util.List;
public class BaseDt {
private Integer bst;
private Date dt;
private BigInteger bg;
private int nt;
private Short sht;
private Long lng;
private Byte bt;
@JacksonXmlCData
private char chr;
private boolean bln;
private float flt;
private double dbl;
private LocalDate ld;
private List<String> testStr;
private Score score;
public Integer getBst() {
return bst;
}
public void setBst(Integer bst) {
this.bst = bst;
}
public Date getDt() {
return dt;
}
public void setDt(Date dt) {
this.dt = dt;
}
public BigInteger getBg() {
return bg;
}
public void setBg(BigInteger bg) {
this.bg = bg;
}
public int getNt() {
return nt;
}
public void setNt(int nt) {
this.nt = nt;
}
public Short getSht() {
return sht;
}
public void setSht(Short sht) {
this.sht = sht;
}
public Long getLng() {
return lng;
}
public void setLng(Long lng) {
this.lng = lng;
}
public Byte getBt() {
return bt;
}
public void setBt(Byte bt) {
this.bt = bt;
}
public char getChr() {
return chr;
}
public void setChr(char chr) {
this.chr = chr;
}
public boolean isBln() {
return bln;
}
public void setBln(boolean bln) {
this.bln = bln;
}
public float getFlt() {
return flt;
}
public void setFlt(float flt) {
this.flt = flt;
}
public double getDbl() {
return dbl;
}
public void setDbl(double dbl) {
this.dbl = dbl;
}
public LocalDate getLd() {
return ld;
}
public void setLd(LocalDate ld) {
this.ld = ld;
}
public List<String> getTestStr() {
return testStr;
}
public void setTestStr(List<String> testStr) {
this.testStr = testStr;
}
public Score getScore() {
return score;
}
public void setScore(Score score) {
this.score = score;
}
@Override
public String toString() {
return "BaseDt [bst=" + bst + ", dt=" + dt + ", bg=" + bg + ", nt=" + nt + ", sht=" + sht + ", lng=" + lng
+ ", bt=" + bt + ", chr=" + chr + ", bln=" + bln + ", flt=" + flt + ", dbl=" + dbl + ", ld=" + ld
+ ", testStr=" + testStr + ", score=" + score + "]";
}
}
Score.java
package com.xxx.demo.common.jsontest;
import java.math.BigDecimal;
public class Score {
private BigDecimal langue;
private BigDecimal math;
private BigDecimal english;
public BigDecimal getLangue() {
return langue;
}
public void setLangue(BigDecimal langue) {
this.langue = langue;
}
public BigDecimal getMath() {
return math;
}
public void setMath(BigDecimal math) {
this.math = math;
}
public BigDecimal getEnglish() {
return english;
}
public void setEnglish(BigDecimal english) {
this.english = english;
}
@Override
public String toString() {
return "Score [langue=" + langue + ", math=" + math + ", english=" + english + "]";
}
}
TestMap.java
package com.xxx.demo.common.jsontest;
import java.util.List;
public class TestMap {
private List<String> mapList;
public List<String> getMapList() {
return mapList;
}
public void setMapList(List<String> mapList) {
this.mapList = mapList;
}
@Override
public String toString() {
return "TestMap [mapList=" + mapList + "]";
}
}
Student.java
package com.xxx.demo.common.jsontest;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Map;
public class Student<T, E> extends Base<BaseDt> {
private String userName;
private Integer age;
private String phone;
private LocalDateTime accessTime;
private LocalTime localTime;
private Score score;
private List<T> grades;
private Map<String, E> mapLt;
private Map<String, String> mapStr;
private Map<String, LocalDateTime> mapLocal;
private List<Map<String, Score>> lscoreList1;
private List<List<Map<String, Score>>> lscoreList2;
private Map<String, Map<String, Map<String, Score>>> mapScore;
private Map<String, List<Score>> mapList;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public LocalDateTime getAccessTime() {
return accessTime;
}
public void setAccessTime(LocalDateTime accessTime) {
this.accessTime = accessTime;
}
public List<T> getGrades() {
return grades;
}
public void setGrades(List<T> grades) {
this.grades = grades;
}
public Map<String, E> getMapLt() {
return mapLt;
}
public void setMapLt(Map<String, E> mapLt) {
this.mapLt = mapLt;
}
public Map<String, String> getMapStr() {
return mapStr;
}
public void setMapStr(Map<String, String> mapStr) {
this.mapStr = mapStr;
}
public Map<String, LocalDateTime> getMapLocal() {
return mapLocal;
}
public void setMapLocal(Map<String, LocalDateTime> mapLocal) {
this.mapLocal = mapLocal;
}
public LocalTime getLocalTime() {
return localTime;
}
public void setLocalTime(LocalTime localTime) {
this.localTime = localTime;
}
public Score getScore() {
return score;
}
public void setScore(Score score) {
this.score = score;
}
public List<Map<String, Score>> getLscoreList1() {
return lscoreList1;
}
public void setLscoreList1(List<Map<String, Score>> lscoreList1) {
this.lscoreList1 = lscoreList1;
}
public List<List<Map<String, Score>>> getLscoreList2() {
return lscoreList2;
}
public void setLscoreList2(List<List<Map<String, Score>>> lscoreList2) {
this.lscoreList2 = lscoreList2;
}
public Map<String, Map<String, Map<String, Score>>> getMapScore() {
return mapScore;
}
public void setMapScore(Map<String, Map<String, Map<String, Score>>> mapScore) {
this.mapScore = mapScore;
}
public Map<String, List<Score>> getMapList() {
return mapList;
}
public void setMapList(Map<String, List<Score>> mapList) {
this.mapList = mapList;
}
@Override
public String toString() {
return "Student [userName=" + userName + ", age=" + age + ", phone=" + phone + ", accessTime=" + accessTime
+ ", localTime=" + localTime + ", score=" + score + ", grades=" + grades + ", mapLt=" + mapLt
+ ", mapStr=" + mapStr + ", mapLocal=" + mapLocal + ", lscoreList1=" + lscoreList1 + ", lscoreList2="
+ lscoreList2 + ", mapScore=" + mapScore + ", mapList=" + mapList + "]";
}
}
用法
JsonUtils类转Springboot2以代码的方式统一配置Jackson->Jackson工具类
package com.xxx.demo.common.jsontest;
import java.util.List;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xxx.demo.common.util.Json2Utils;
import com.xxx.demo.common.util.JsonUtils;
import com.xxx.demo.common.util.XmlUtils;
public class Json2Test {
public static void main(String[] args) {
ObjectMapper mapper1 = JsonUtils.getObjectMapper();
String json = Json2Utils.clazz2Json(mapper1, new TypeReference<List<List<Student<Score, TestMap>>>>() {});
System.out.println(json);
ObjectMapper mapper2 = XmlUtils.getObjectMapper();
String xml = Json2Utils.clazz2Json(mapper2, new TypeReference<Student<Score, TestMap>>() {});
System.out.println(xml);
}
}
转换结果
[ [ {
"address" : null,
"listDt" : [ {
"bst" : null,
"dt" : null,
"bg" : null,
"nt" : 0,
"sht" : null,
"lng" : null,
"bt" : null,
"chr" : "\u0000",
"bln" : false,
"flt" : 0.0,
"dbl" : 0.0,
"ld" : null,
"testStr" : [ null ],
"score" : {
"langue" : null,
"math" : null,
"english" : null
}
} ],
"userName" : null,
"age" : null,
"phone" : null,
"accessTime" : null,
"localTime" : null,
"score" : {
"langue" : null,
"math" : null,
"english" : null
},
"mapLt" : {
"KEY_0" : {
"mapList" : [ null ]
}
},
"mapStr" : {
"KEY_0" : null
},
"mapLocal" : {
"KEY_0" : null
},
"lscoreList1" : [ {
"KEY_0" : {
"langue" : null,
"math" : null,
"english" : null
}
} ],
"lscoreList2" : [ [ {
"KEY_0" : {
"langue" : null,
"math" : null,
"english" : null
}
} ] ],
"mapScore" : {
"KEY_0" : {
"KEY_0" : {
"KEY_0" : {
"langue" : null,
"math" : null,
"english" : null
}
}
}
},
"mapList" : {
"KEY_0" : [ {
"langue" : null,
"math" : null,
"english" : null
} ]
},
"gg" : [ {
"langue" : null,
"math" : null,
"english" : null
} ]
} ] ]
<Student>
<address></address>
<listDt>
<listDt>
<bst></bst>
<dt></dt>
<bg></bg>
<nt>0</nt>
<sht></sht>
<lng></lng>
<bt></bt>
<chr><![CDATA[ ]]></chr>
<bln>false</bln>
<flt>0.0</flt>
<dbl>0.0</dbl>
<ld></ld>
<testStr>
<testStr></testStr>
</testStr>
<score>
<langue></langue>
<math></math>
<english></english>
</score>
</listDt>
</listDt>
<userName></userName>
<age></age>
<phone></phone>
<accessTime></accessTime>
<localTime></localTime>
<score>
<langue></langue>
<math></math>
<english></english>
</score>
<mapLt>
<KEY_0>
<mapList>
<mapList></mapList>
</mapList>
</KEY_0>
</mapLt>
<mapStr>
<KEY_0></KEY_0>
</mapStr>
<mapLocal>
<KEY_0></KEY_0>
</mapLocal>
<lscoreList1>
<lscoreList1>
<KEY_0>
<langue></langue>
<math></math>
<english></english>
</KEY_0>
</lscoreList1>
</lscoreList1>
<lscoreList2>
<lscoreList2>
<KEY_0>
<langue></langue>
<math></math>
<english></english>
</KEY_0>
</lscoreList2>
</lscoreList2>
<mapScore>
<KEY_0>
<KEY_0>
<KEY_0>
<langue></langue>
<math></math>
<english></english>
</KEY_0>
</KEY_0>
</KEY_0>
</mapScore>
<mapList>
<KEY_0>
<langue></langue>
<math></math>
<english></english>
</KEY_0>
</mapList>
<gg>
<gg>
<langue></langue>
<math></math>
<english></english>
</gg>
</gg>
</Student>
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。