【问题标题】:Fill empty values based on parent values of nested JSON Object with Gson使用 Gson 根据嵌套 JSON 对象的父值填充空值
【发布时间】:2020-12-07 18:46:55
【问题描述】:

我正在反序列化一个 JSON 数据结构,如下面的 GSON 示例:

{
  "id": 1,
  "data": [
    {
      "value": 2
    },
    {
      "value": 2
    }
  ]
}

此 JSON 映射到以下类:

class Element {
   Integer id;
   List<SubElement> data;
   ...
}

class SubElement {
   Integer id;
   Integer value;
   ...
}

我希望能够在反序列化时使用 GSON 填充基于父 id 字段的 SubElement 对象的字段 id

这样做的目的是我在我的应用程序的几个部分收到这种 JSON,例如我想省略这种代码:

child.setId(parent.getId());

我尝试实现自定义反序列化器JsonDeserializer&lt;SubElement&gt;,但我无权访问根元素,因此无权访问id


有没有办法进行这种类型的自定义反序列化?还是我应该继续使用Reflection 实现某种解决方案,例如遍历整个对象以寻找感兴趣的领域并相应地更新它?

我正在寻找一种通用解决方案,它可能对缺少id 的其他嵌套对象有效。

【问题讨论】:

    标签: java json gson


    【解决方案1】:

    有没有办法进行这种类型的自定义反序列化?

    是的,但它不一定需要成为 Gson 反序列化的一部分,除非您希望将其集中化。调用 fromJson 方法后,您始终可以调整对象(因此不那么可靠)。因此,如果您认为 Gson 应该对此负责,您可以将其实现为后处理器:

    public interface IPostProcessorResolver<T> {
    
        @Nullable
        Consumer<T> resolvePostProcessor(@Nonnull TypeToken<?> typeToken);
    
    }
    
    public final class PostProcessingTypeAdapterFactory
            implements TypeAdapterFactory {
    
        private final IPostProcessorResolver<?> resolvePostProcessor;
    
        private PostProcessingTypeAdapterFactory(final IPostProcessorResolver<?> resolvePostProcessor) {
            this.resolvePostProcessor = resolvePostProcessor;
        }
    
        public static TypeAdapterFactory create(final IPostProcessorResolver<?> resolvePostProcessor) {
            return new PostProcessingTypeAdapterFactory(resolvePostProcessor);
        }
    
        @Override
        @Nullable
        public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
            @Nullable
            @SuppressWarnings("unchecked")
            final Consumer<T> postProcessor = (Consumer<T>) resolvePostProcessor.resolvePostProcessor(typeToken);
            if ( postProcessor == null ) {
                return null;
            }
            final TypeAdapter<T> delegateTypeAdapter = gson.getDelegateAdapter(this, typeToken);
            return new TypeAdapter<T>() {
                @Override
                public void write(final JsonWriter out, final T value)
                        throws IOException {
                    delegateTypeAdapter.write(out, value);
                }
    
                @Override
                public T read(final JsonReader in)
                        throws IOException {
                    // First, read the object
                    final T object = delegateTypeAdapter.read(in);
                    // Second, tell it to adjust itself
                    postProcessor.accept(object);
                    return object;
                }
            };
        }
    
    }
    

    然后,进行测试:

    final Gson gson = new GsonBuilder()
            .registerTypeAdapterFactory(PostProcessingTypeAdapterFactory.create((IPostProcessorResolver<Element>) typeToken -> {
                if ( typeToken.getRawType() != Element.class ) {
                    return null;
                }
                return element -> {
                    if ( element.data == null ) {
                        return;
                    }
                    for ( @Nullable final SubElement datum : element.data ) {
                        if ( datum != null ) {
                            datum.id = element.id;
                        }
                    }
                };
            }))
            .create();
    ...
    final Element element = gson.fromJson(jsonReader, Element.class);
    Assertions.assertNotNull(element.data);
    Assertions.assertEquals(1, (int) element.id);
    Assertions.assertEquals(1, (int) element.data.get(0).id);
    Assertions.assertEquals(1, (int) element.data.get(1).id);
    

    请注意,您可以通过仅实现IPostProcessorResolver 来实现更复杂的策略:多类型支持与类型解析;反射使用;等等

    【讨论】:

    • 看起来很接近我想要的东西。让我试一试!
    猜你喜欢
    • 2018-05-25
    • 2017-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-14
    • 2015-09-16
    • 2022-09-29
    相关资源
    最近更新 更多