首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >Gson -如何进行特殊处理,如屏蔽

Gson -如何进行特殊处理,如屏蔽
EN

Stack Overflow用户
提问于 2021-04-21 09:18:02
回答 1查看 52关注 0票数 1

如何配置Gson对toJson的值进行额外的处理?

代码语言:javascript
代码运行次数:0
运行
复制
public class MyClass{
    @SerializedName("qwerty")
    @Mask(exposeFront=2, exposeRear=2, mask="*")
    private String qwerty
}

假设MyClass#qwerty的值为1234567890,如何将Gson设置为输出{"qwerty":"12******90"}

EN

回答 1

Stack Overflow用户

发布于 2021-04-21 10:18:34

负责“普通”对象序列化和反序列化的@Masked ReflectiveTypeAdapterFactory无法增强以支持任何其他注释,如Gson。它只能使用@Expose (间接通过排除策略)、@SerializedName和其他一些注释,如@Since@Until (也可以使用排除策略)。注意:默认情况下,文档中记录并支持这些注释。一般来说,Gson建议对声明类使用类型适配器MyClass,但这也意味着您必须管理所有字段,并确保在类更改后更新相应的类型适配器。更糟糕的是,添加自定义类型适配器会使这些批注的支持丢失。

另一种解决方法是注入一个特殊的字符串类型适配器工厂,该工厂可以做到这一点,但由于它的注入机制,这是有限的,并且需要复制@Masked注释值(如果您在代码中的其他地方使用该注释)和@JsonAdapter中的类型适配器工厂配置。

代码语言:javascript
代码运行次数:0
运行
复制
public abstract class MaskedTypeAdapterFactory
        implements TypeAdapterFactory {

    private final int exposeFront;
    private final int exposeRear;
    private final char mask;

    private MaskedTypeAdapterFactory(final int exposeFront, final int exposeRear, final char mask) {
        this.exposeFront = exposeFront;
        this.exposeRear = exposeRear;
        this.mask = mask;
    }

    // must be "baked" into the class (name only represents the configuration)
    public static final class _2_2_asterisk
            extends MaskedTypeAdapterFactory {

        private _2_2_asterisk() {
            super(2, 2, '*');
        }

    }

    @Override
    @Nullable
    public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
        if ( typeToken.getRawType() != String.class ) {
            return null;
        }
        @SuppressWarnings("unchecked")
        final TypeAdapter<String> delegate = (TypeAdapter<String>) gson.getAdapter(typeToken);
        final TypeAdapter<String> typeAdapter = new TypeAdapter<String>() {
            @Override
            public void write(final JsonWriter out, final String value)
                    throws IOException {
                // mask the value
                final int length = value.length();
                final char[] buffer = value.toCharArray();
                for ( int i = exposeFront; i < length - exposeRear; i++ ) {
                    buffer[i] = mask;
                }
                out.value(new String(buffer));
            }

            @Override
            public String read(final JsonReader in)
                    throws IOException {
                return delegate.read(in);
            }
        }
                .nullSafe();
        @SuppressWarnings("unchecked")
        final TypeAdapter<T> adapter = (TypeAdapter<T>) typeAdapter;
        return adapter;
    }

}
代码语言:javascript
代码运行次数:0
运行
复制
@NoArgsConstructor
@AllArgsConstructor
final class MyClass {

    @SerializedName("qwerty")
    @Mask(exposeFront = 2, exposeRear = 2, mask = "*")
    // unfortunately, this must duplicate the @Mask annotation values
    // since type adapter (factories) do not accept supplemental information
    // and Java annotations can only accept compile-time constants
    @JsonAdapter(MaskedTypeAdapterFactory._2_2_asterisk.class)
    @SuppressWarnings("unused")
    private String qwerty;

}

测试:

代码语言:javascript
代码运行次数:0
运行
复制
public final class MaskedTypeAdapterFactoryTest {

    private static final Gson gson = new GsonBuilder()
            .disableHtmlEscaping()
            .disableInnerClassSerialization()
            .create();

    @Test
    public void test() {
        final String actual = gson.toJson(new MyClass("1234567890"));
        final String expected = "{\"qwerty\":\"12******90\"}";
        Assertions.assertEquals(expected, actual);
    }

}

在Gson中,这可能是最健壮的方式。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67188120

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档