gson-如何进行掩蔽等特殊处理

j7dteeu8  于 2021-07-09  发布在  Java
关注(0)|答案(1)|浏览(352)

如何配置gson对tojson的值进行额外的处理?

public class MyClass{
    @SerializedName("qwerty")
    @Mask(exposeFront=2, exposeRear=2, mask="*")
    private String qwerty
}

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

unftdfkk

unftdfkk1#

格森 ReflectiveTypeAdapterFactory ,负责“普通”对象序列化和反序列化,不可能增强以支持任何其他注解,如 @Masked . 它只能使用如下注解 @Expose (间接通过排除策略), @SerializedName 还有一些人喜欢 @Since 以及 @Until (也是排除策略)。注意:这些注解是文档化的,默认情况下是受支持的。一般来说,gson建议对声明类使用类型适配器, MyClass ,但这也意味着您必须管理所有字段,并确保在更改类后更新相应的类型适配器。更糟糕的是,添加自定义类型适配器会使这些注解失去支持。
另一种解决方法是注入一个特殊的字符串类型的适配器工厂,它可以完成这个任务,但是由于注入机制的原因,这既有局限性,又需要复制 @Masked 注解值(如果您在代码的其他地方使用注解)和中的类型适配器工厂配置 @JsonAdapter .

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;
    }

}
@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;

}

测试:

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中最强大的方法。

相关问题