13

次の POJO があるとします。

class Pojo {
    String s;
    Object o;
    Map<String, String> m;
}

そして、実行時に、1 つを除くすべてのプロパティのデフォルトのシリアル化/逆シリアル化が必要です。通常、この他の質問と同様に、シリアル化するときにデータベース内のフィールドを ID で置き換えたいと考えています。

たとえばo、外部マッピングから取得した文字列に置き換えたい (例: object1<=> "123" およびobject2<=> "456"):

  • シリアル化: 読み取りoと置換 (つまりoobject1文字列 "123" としてシリアル化)
  • 逆シリアル化: "123" を読み取り、いくつかのテーブルにクエリを実行して元の値を取得しo(つまりobject1)、 でPojoオブジェクトを再作成しますo = object1

モジュールがそれを行う1つの方法であることは理解していますが、変更する必要のないプロパティの自動BeanSerializer/Deserializerを維持しながらモジュールを使用する方法がわかりません。

誰かが例(たとえ不自然であっても)または別のアプローチを与えることができますか?


ノート:

  • コンパイル時に変更が不明であるため、注釈や Mixin を使用できません (つまり、特定できない方法でプロパティが変更される可能性があります)。
  • この他の質問は、仕事をしているように見えるCustomSerializerFactoryの使用を指しています。残念ながら、公式サイトでは、これは推奨されるアプローチではなくなり、代わりにモジュールを使用する必要があることが示されています。

編集

もう少し明確にするために、たとえば、Mixins を使用して次のことができます。

ObjectMapper mapper = new ObjectMapper(MongoBsonFactory.createFactory());
mapper.addMixInAnnotations(Pojo.class, PojoMixIn.class);

ObjectReader reader = mapper.reader(Pojo.class);
DBEncoder dbEncoder = DefaultDBEncoder.FACTORY.create();
OutputBuffer buffer = new BasicOutputBuffer();
dbEncoder.writeObject(buffer, o);

次の Mixin を使用します。

abstract class PojoMixIn {
    @JsonIgnore Object o;
}

次に、必要な文字列を JSON コンテンツに追加します。しかし、コンパイル時に、o置き換える必要があるのはフィールドであることを知る必要がありますが、そうではありません。

4

1 に答える 1

19

私はあなたが必要としているものだと思い@JsonSerializeます@JsonDeserialize。これらの注釈により、特定のフィールドのシリアル化/逆シリアル化を制御できます。この質問は、それらを 1 つの注釈に結合するエレガントな方法を示しています。

アップデート。この複雑なシナリオでは、BeanSerializerModifier/BeanDeserializerModifierクラスを見ることができます。アイデアはBeanSerializer/BeanDeserializer、特定のフィールドのカスタム ロジックで一般的な変更を行い、基本的な実装で他のことを実行できるようにすることです。しばらくしてから例を投稿します。

UPD2. ご覧のとおり、方法の 1 つは、changePropertiesメソッドを使用して独自のシリアライザーを割り当てることです。

UPD3. カスタム シリアライザーの動作例を更新しました。逆シリアル化も同様の方法で実行できます。

UPD4. 完全なカスタム シリアライゼーション/デシリアライゼーションで例を更新しました。(私はjakson-mapper-asl-1.9.8を使用しました)

  public class TestBeanSerializationModifiers {

    static final String PropertyName = "customProperty";
    static final String CustomValue = "customValue";
    static final String BaseValue = "baseValue";

    // Custom serialization

    static class CustomSerializer extends JsonSerializer<Object> {
        @Override
        public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
            String customValue = CustomValue; // someService.getCustomValue(value);
            jgen.writeString(customValue);
        }
    }

    static class MyBeanSerializerModifier extends BeanSerializerModifier {
        @Override
        public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BasicBeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
            for (int i = 0; i < beanProperties.size(); i++) {
                BeanPropertyWriter beanPropertyWriter = beanProperties.get(i);
                if (PropertyName.equals(beanPropertyWriter.getName())) {
                    beanProperties.set(i, beanPropertyWriter.withSerializer(new CustomSerializer()));
                }
            }
            return beanProperties;
        }
    }

    // Custom deserialization

    static class CustomDeserializer extends JsonDeserializer<Object> {
        @Override
        public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
            // serialized value, 'customValue'
            String serializedValue = jp.getText();
            String baseValue = BaseValue; // someService.restoreOldValue(serializedValue);
            return baseValue;
        }
    }

    static class MyBeanDeserializerModifier extends BeanDeserializerModifier {
        @Override
        public BeanDeserializerBuilder updateBuilder(DeserializationConfig config, BasicBeanDescription beanDesc, BeanDeserializerBuilder builder) {
            Iterator<SettableBeanProperty> beanPropertyIterator = builder.getProperties();
            while (beanPropertyIterator.hasNext()) {
                SettableBeanProperty settableBeanProperty = beanPropertyIterator.next();
                if (PropertyName.equals(settableBeanProperty.getName())) {
                    SettableBeanProperty newSettableBeanProperty = settableBeanProperty.withValueDeserializer(new CustomDeserializer());
                    builder.addOrReplaceProperty(newSettableBeanProperty, true);
                    break;
                }
            }
            return builder;
        }
    }

    static class Model {

        private String customProperty = BaseValue;
        private String[] someArray = new String[]{"one", "two"};

        public String getCustomProperty() {
            return customProperty;
        }

        public void setCustomProperty(String customProperty) {
            this.customProperty = customProperty;
        }

        public String[] getSomeArray() {
            return someArray;
        }

        public void setSomeArray(String[] someArray) {
            this.someArray = someArray;
        }
    }

    public static void main(String[] args) {
        SerializerFactory serializerFactory = BeanSerializerFactory
                .instance
                .withSerializerModifier(new MyBeanSerializerModifier());

        DeserializerFactory deserializerFactory = BeanDeserializerFactory
                .instance
                .withDeserializerModifier(new MyBeanDeserializerModifier());

        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializerFactory(serializerFactory);
        objectMapper.setDeserializerProvider(new StdDeserializerProvider(deserializerFactory));

        try {
            final String fileName = "test-serialization.json";
            // Store, "customValue" -> json
            objectMapper.writeValue(new File(fileName), new Model());
            // Restore, "baseValue" -> model
            Model model = objectMapper.readValue(new File(fileName), Model.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
于 2013-02-24T12:51:23.910 に答える