java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Jackson2 JsonSchema java实体类生成json

Jackson2的JsonSchema实现java实体类生成json方式

作者:daodfs1

这篇文章主要介绍了Jackson2的JsonSchema实现java实体类生成json,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

除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("");
   }   
  });
 }
 
 /**
  * 普通java类转json字符串
  * @param <T>
  * @param mapper
  * @param clazz
  * @return
  */
 public static <T> String clazz2Json(ObjectMapper mapper, Class<T> clazz) {
  JavaType javaType = mapper.getTypeFactory().constructType(clazz);
  return javaType2Json(mapper, javaType);
 }
 
 /**
  * 泛型java类转json字符串
  * @param <T>
  * @param mapper
  * @param reference
  * @return
  */
 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>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文