从Java中的嵌套空对象创建示例JSON
我正在尝试创建一个实用程序来打印来自任何给定POJO的示例JSON结构。我一直在尝试Jackson和Gson打印给定对象的所有字段。我创建了以下三个对象作为示例从Java中的嵌套空对象创建示例JSON,java,json,serialization,jackson,gson,Java,Json,Serialization,Jackson,Gson,我正在尝试创建一个实用程序来打印来自任何给定POJO的示例JSON结构。我一直在尝试Jackson和Gson打印给定对象的所有字段。我创建了以下三个对象作为示例 public class Model { private String val1; private Child child; //getters and setters } public class Child { private String val2; private ArrayList&l
public class Model {
private String val1;
private Child child;
//getters and setters
}
public class Child {
private String val2;
private ArrayList<SubChild> subChildren;
//getters and setters
}
public class SubChild {
private String val3;
//getters and setters
}
这些是我试图打印这些POJO及其输出的方法,它们不太符合我的需要
杰克逊:
ObjectMapper map = new ObjectMapper().setSerializationInclusion(Include.ALWAYS);
Model testModel = new Model()
map.writerWithDefaultPrettyPrinter().writeValueAsString(testModel);
输出:
{
"val1" : null,
"child" : null
}
{
"val1" : null,
"child" : null
}
{
"s3": "",
"lo4": [
{
"s4a": "",
"s4b": ""
}
],
"s2": "",
"s1": ""
}
格森:
输出:
{
"val1" : null,
"child" : null
}
{
"val1" : null,
"child" : null
}
{
"s3": "",
"lo4": [
{
"s4a": "",
"s4b": ""
}
],
"s2": "",
"s1": ""
}
有没有一种简单的方法可以在不填充所有子字段的情况下实现我的目标?我希望能够在泛型类上使用此实用程序,因为在泛型类中,我不知道要调用哪些方法来用空值填充对象。我看不出这是如何实现的。如果有一个
Long
作为字段会怎么样?杰克逊不知道在那里该做什么。杰克逊和格森所做的是正确的,他们打印了null
您可以编写一个实用程序来手动设置字段。但是,您必须相应地处理不同的类型。像这样的东西可以满足您的要求,但仅限于列表
:
public static void main(String args[]) throws IOException, IllegalAccessException {
ObjectMapper map = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.ALWAYS);
Model testModel = new Model();
instantiateFields(testModel);
String result = map.writerWithDefaultPrettyPrinter().writeValueAsString(testModel);
System.out.println(result);
}
private static void instantiateFields(Object o) throws IllegalAccessException {
Field[] fields = o.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
if (field.get(o) == null) {
Type type = field.getType();
try {
Class<?> clazz = (Class<?>) type;
Object instance = clazz.newInstance();
if (List.class.isAssignableFrom(clazz)) {
instantiateList(clazz, field, instance);
}
field.set(o, instance);
instantiateFields(instance);
} catch (ClassCastException | InstantiationException e) {
// Handle this or leave field null
}
}
}
}
private static void instantiateList(Class<?> clazz, Field field, Object instance) throws IllegalAccessException, InstantiationException {
ParameterizedType listType = (ParameterizedType) field.getGenericType();
Class<?> listClass = (Class<?>) listType.getActualTypeArguments()[0];
Object listTypeInstance = listClass.newInstance();
instantiateFields(listTypeInstance);
List<Object> list = (List<Object>) instance;
list.add(listTypeInstance);
}
希望这能有所帮助。我怀疑任何库都不会支持这种开箱即用的方式,因为它们唯一的职责是处理序列化/反序列化。 因此,为了使任何序列化程序按您所希望的方式工作,最好创建一个对象模拟,然后尝试为特定库调整模拟策略 首先,让我们为类型创建一个简单的实用程序类:
最终类类型{
私有类型(){
}
静态类typeToClass(最终类型){
最后一节课;
if(类型instanceof Class){
clazz=(类)类型;
}else if(参数化类型的instanceof){
最终参数化类型参数化类型=(参数化类型)类型;
clazz=typeToClass(parameterizedType.getRawType());
}否则{
抛出新的断言错误(类型);
}
@抑制警告(“未选中”)
最后一节课castClass=(Class)clazz;
返回类;
}
}
上面的方法只负责从类型解析类(至少它尝试这样做)。
类是类型,但类型不一定是类。
这就是Java类型的系统
下一个类负责按类型模拟对象。
这有点困难,但这些评论会让人有所了解(ImmutableMap
和ImmutableList
来自谷歌番石榴)
final类模拟{
//缓存不可变的原语和包装。它是安全的
私有静态最终可选defaultByte=Optional.of((字节)0);
private static final Optional defaultShort=Optional.of((short)0);
私有静态最终可选defaultInteger=Optional.of(0);
private static final Optional defaultLong=Optional.of(0L);
private static final Optional defaultFloat=Optional.of(0F);
私有静态最终可选defaultDouble=Optional.of(0D);
private static final Optional defaultCharacter=Optional.of('\u0000');
private static final Optional defaultBoolean=Optional.of(false);
private static final Optional defaultString=Optional.of(“”);
//这是一个可以按已知类型返回值的简单映射
私有静态最终映射>defaultObjectsByIndex=ImmutableMap.>builder()
.put(byte.class,defaultByte).put(byte.class,defaultByte)
.put(short.class,defaultShort)put(short.class,defaultShort)
.put(int.class,defaultInteger).put(Integer.class,defaultInteger)
.put(long.class,defaultLong).put(long.class,defaultLong)
.put(float.class,defaultFloat).put(float.class,defaultFloat)
.put(double.class,defaultDouble).put(double.class,defaultDouble)
.put(Character.class,defaultCharacter).put(Character.class,defaultCharacter)
.put(boolean.class,defaultBoolean).put(boolean.class,defaultBoolean)
.put(String.class,defaultString)
.build();
//与上一个贴图不同,搜索对象采用线性类型
//将使用第一个最佳候选人
//下面声明了ifAssignable方法
私有静态最终集合>>defaultObjectsByFirstBest=ImmutableList.maybeT=defaultInstanceSupplier.apply(类型);
if(maybeT.isPresent()){
@抑制警告(“未选中”)
final T castT=(T)postProcess.apply(maybeT.get(),type);
返回浇铸;
}
最终类clazz=Types.typeToClass(type);
//否?那么让我们尝试实例化它
最终T newT=objectCreator.apply(clazz);
//并从下到上迭代到超类(java.lang.Object没有字段)
for(Class i=clazz;i!=null&&i!=Object.Class;i=i.getSuperclass()){
for(最终字段:i.getDeclaredFields()){
如果(isFieldSupported.test(field)){
字段。setAccessible(true);
//递归地对所有字段执行相同的操作
最终对象值=创建(field.getGenericType(),defaultInstanceSupplier,isTypeSupported,isFieldSupported,objectCreator,后处理);
字段设置(牛顿,值);
}
}
}
//然后对这些“特殊”类型进行后处理
@抑制警告(“未选中”)
final T castNewT=(T)postProcess.apply(newT,type);
返回卡斯特纽特;
}
静态可选supplyDefaultInstance(最终类型){
最终可选的defaultValueFromIndex=defaultObjectsByIndex.get(类型);
如果(defaultValueFromIndex!=null){
返回defaultValueFromIndex;
}
返回defaultObjectsByFirstBest
.stream()
.map(冲突解决程序->冲突解决程序.apply(典型