如何使用 Java 类定义中的虚拟数据生成 JSON 样本? (注意:我不是在问从 POJO 生成 JSON。这是之前在 stackoverflow 上问过的问题)。
我想要的是直接从 Java 类生成一些示例虚拟数据。例如你有这样一个类:
public class Reservation {
@ApiModelProperty(value = "")
private Traveller leadTraveller = null;
@ApiModelProperty(example = "2", value = "")
private Integer sourceSystemID = null;
@ApiModelProperty(value = "")
private String recordLocation = null;
@ApiModelProperty(example = "2010", value = "")
private Integer recordLocatorYear = null;
}
然后你有一个函数,它在不创建 POJO 的情况下生成一个具有虚拟值的 JSON 字符串,例如:
{
"leadTraveller": {
"firstNames": "firstNames",
"lastName": "lastName",
"email": "email",
"travellerGUID": "travellerGUID",
"travellerRefs": [{
"customerReportingRank": 37,
"value": "value",
"description": "description"
}]
},
"sourceSystemID": 38,
"recordLocation": "recordLocation",
"recordLocatorYear": 9
}
是否有默认情况下可以执行此操作的库?
我尝试使用具有这些 Maven 依赖项的 Java 代码来解决这个问题:
<dependency>
<groupId>fctg-ngrp</groupId>
<artifactId>model-core</artifactId>
<version>1.0.4-SNAPSHOT-MODEL-CORE</version>
</dependency>
<dependency>
<groupId>io.vavr</groupId>
<artifactId>vavr</artifactId>
<version>0.9.2</version>
<scope>test</scope>
</dependency>
Jackson主要用于校验和格式化输出的JSON。
下面是我使用的 Java 代码:
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.io.Files;
import io.vavr.API;
import io.vavr.collection.Array;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
/**
* Sample utility for generating dummy JSON sample code from a JAva class directly.
*/
public class GenerateJSONFromClasses {
private static final Random R = new Random();
/**
* Used to avoid infinite loops.
*/
private static final Map<Class<?>, Integer> visited = new HashMap<>();
private static final ObjectMapper mapper = new ObjectMapper();
public static void main(String[] args) throws IOException {
Class<Reservation> clazz = Reservation.class;
generateDummyJSON(clazz, args);
}
public static void generateDummyJSON(Class<Reservation> clazz, String... paths) throws IOException {
StringWriter out = new StringWriter();
try (PrintWriter writer = new PrintWriter(out)) {
writer.println(printObj(clazz));
JsonNode jsonNode = mapper.readTree(out.toString());
String prettyJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode);
if (paths == null || paths.length == 0) {
System.out.println(prettyJson);
} else {
Array.of(paths).map(sPath -> Paths.get(sPath))
.map(Path::toFile)
.map(API.unchecked(file -> {
Files.write(prettyJson, file, StandardCharsets.UTF_8);
return file;
}));
}
}
}
private static String printObj(Class<?> clazz) {
if (!visited.containsKey(clazz) || visited.get(clazz) <= 1) {
visited.merge(clazz, 1, (integer, integer2) -> integer + integer2);
Field[] declaredFields = clazz.getDeclaredFields();
return "{" +
Array.of(declaredFields).map(field -> String.format(" \"%s\" : %s%n", field.getName(), printFieldValue(field)))
.collect(Collectors.joining(String.format(",%n"))) +
"}";
}
return "";
}
private static Object printFieldValue(Field field) {
Class<?> fieldType = field.getType();
if (String.class.equals(fieldType)) {
return String.format("\"%s\"", field.getName());
} else if (Integer.class.equals(fieldType)) {
return R.nextInt(99) + 1;
} else if (LocalDate.class.equals(fieldType)) {
return String.format("\"%s\"", LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
} else if (LocalDateTime.class.equals(fieldType)) {
return String.format("\"%s\"", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")));
} else if (OffsetDateTime.class.equals(fieldType)) {
return String.format("\"%s\"", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")));
} else if (Date.class.equals(fieldType)) {
return System.currentTimeMillis();
} else if (List.class.equals(fieldType)) {
ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
Class<?> clazz = (Class<?>) parameterizedType.getActualTypeArguments()[0];
return String.format("[%s]", printObj(clazz));
} else if (fieldType.isAssignableFrom(Number.class)) {
return R.nextDouble() * 10.0;
} else if (BigDecimal.class.equals(fieldType)) {
return new BigDecimal(R.nextDouble() * 10.0);
} else if (Boolean.class.equals(fieldType)) {
return R.nextBoolean();
} else {
return printObj(fieldType);
}
}
}
最佳答案
感谢@gil.fernandes, 我使用了您的代码并稍作修改。
1) 允许多次使用同一类型,但将访问次数保持在 100 以防止无限循环。我以为您的用例有所不同。
2) 添加了 java.util.Date 和 Enum。
3) 打印虚拟值作为类的简单名称。在枚举的情况下,打印出“String of”及其值的列表。
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.io.Files;
import com.jnj.na.webmethods.core.dto.MaterialWsDTO;
import io.vavr.API;
import io.vavr.collection.Array;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.util.*;
import java.util.stream.Collectors;
/**
* Sample utility for generating dummy JSON sample code from a JAva class directly.
*/
public class GenerateJSONFromClasses {
/**
* Used to avoid infinite loops.
*/
private static final Map<Class<?>, Integer> visited = new HashMap<>();
private static final ObjectMapper mapper = new ObjectMapper();
public static void main(String[] args) throws IOException {
Class<MaterialWsDTO> clazz = MaterialWsDTO.class;
generateDummyJSON(clazz, args);
}
public static void generateDummyJSON(Class<MaterialWsDTO> clazz, String... paths) throws IOException {
StringWriter out = new StringWriter();
try (PrintWriter writer = new PrintWriter(out)) {
writer.println(printObj(clazz));
JsonNode jsonNode = mapper.readTree(out.toString());
String prettyJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode);
if (paths == null || paths.length == 0) {
System.out.println(prettyJson);
} else {
Array.of(paths).map(sPath -> Paths.get(sPath))
.map(Path::toFile)
.map(API.unchecked(file -> {
Files.write(prettyJson, file, StandardCharsets.UTF_8);
return file;
}));
}
}
}
private static String printObj(Class<?> clazz) {
if (!visited.containsKey(clazz) || visited.get(clazz) <= 100) {
visited.merge(clazz, 1, (integer, integer2) -> integer + integer2);
Field[] declaredFields = clazz.getDeclaredFields();
return "{" +
Array.of(declaredFields)
.filterNot(e->Modifier.isStatic(e.getModifiers()))
.map(field -> String.format(" \"%s\" : %s%n", field.getName(), printFieldValue(field)))
.collect(Collectors.joining(String.format(",%n"))) +
"}";
}
return "";
}
private static Object printFieldValue(Field field) {
Class<?> fieldType = field.getType();
if (String.class.equals(fieldType)) {
return name(fieldType);
} else if (Integer.class.equals(fieldType)) {
return name(fieldType);
} else if (Enum.class.isAssignableFrom(fieldType)) {
return printEnum(fieldType);
} else if (Double.class.equals(fieldType)) {
return name(fieldType);
} else if (LocalDate.class.equals(fieldType)) {
return name(fieldType);
} else if (LocalDateTime.class.equals(fieldType)) {
return name(fieldType);
} else if (OffsetDateTime.class.equals(fieldType)) {
return name(fieldType);
} else if (Date.class.equals(fieldType)) {
return name(fieldType);
} else if (List.class.equals(fieldType)) {
ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
Class<?> clazz = (Class<?>) parameterizedType.getActualTypeArguments()[0];
return String.format("[%s]", printObj(clazz));
} else if (fieldType.isAssignableFrom(Number.class)) {
return name(fieldType);
} else if (BigDecimal.class.equals(fieldType)) {
return name(fieldType);
} else if (Boolean.class.equals(fieldType)) {
return name(fieldType);
} else {
return printObj(fieldType);
}
}
private static String printEnum(Class<?> fieldType) {
Field[] declaredFields = fieldType.getDeclaredFields();
return "\"String of " + Arrays.stream(declaredFields)
.filter(field -> field.getType()==fieldType)
.map(Field::getName)
.collect(Collectors.joining(",")) +
"\"";
}
private static Object name(Class<?> fieldType) {
return "\""+fieldType.getSimpleName()+"\"";
}
}
关于java - 从 Java 类生成 JSON 示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51673259/