2013-02-22 11 views
11

でカスタムの方法での私は、次のPOJOを持っている想像してみましょう: (縮小)シリアル化ビーンは、実行時

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

実行時に

は、私は1つを除くすべてのプロパティのデフォルトのシリアライズ/デシリアライズします。通常、私は、フィールドの代わりに、フィールドのIDをデータベースで、シリアル化するときは、 this other questionと同様です。

例えば、私は(例:object1 < => "123" とobject2 < => "456"):外部マッピングから取得した文字列でoを交換したい

  • 連載:読み取りoと(oobject1であればそう、文字列「123」としてシリアライズ)
  • デシリアライゼーションの置き換え:Pojo OBJECを再作成、バックo(すなわちobject1)の元の値を取得するには、いくつかのテーブルを照会し、「123」をお読みにtはo = object1です。

私はモジュールはそれを行うための一つの方法であろうと理解が、私は変更する必要はありませんプロパティの自動のBeanSerializer /デシリアライザを維持しながら、それらを使用するかどうかはわかりません。

誰かが例を挙げることはできますか(工夫されていることもあります)


  • 変化(すなわち、任意の特性が決定ではない方法で変更される可能性があります)コンパイル時に知られていないように私は、注釈またはミックスインを使用することはできません。
  • This other questionは、CustomSerializerFactoryを使用していることを示しています。残念ながら、公式サイトにはit is not the recommended approach any moreとそのモジュールが代わりに使用されるべきであることが示されています。

編集

少し明確であるために、私は、例えばミックスインで、次の操作を行うことができます

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フィールドを置き換える必要があることを知る必要があります。

+0

(私はjaksonマッパー-ASL-1.9.8を使用している)>変更は、コンパイル時に不明であると私は注釈やミックスインを使用することはできません(つまり、すべてのプロパティが>方法で変更される可能性がありますそれは決定できません)。明確にしてください。非常に混乱しています。なぜなら、 "Notes:"の上にあるものは全て静的であり、コンパイル時に知られているからです。クラス(Pojo)とPojoのフィールドは事前に分かっていませんか? –

+0

クラス構造を想定するのは安全ではないとお考えですか? Raw(untyped/simple)データバインディングは、JSON構造体をLinkedHashMap 、配列JSON構造体としてArrayList 、およびプリミティブJSONフィールドをJavaプリミティブラッパーとしてdeserialisesします。 –

+0

@GlenBestはいPojoクラスは多かれ少なかれ可能性があります。私は 'o'がStringに置き換えられた例を挙げました。しかし、プログラムの後半では、文字列で置き換えられる必要がある 'm'があり、' o'は「通常」シリアル化されます。 – assylias

答えて

15

私は@JsonSerialize@JsonDeserializeが必要だと思います。これらのアノテーションは、特定のフィールドのシリアライズ/デシリアライズを制御します。 This questionは、それらを1つのアノテーションに結合するエレガントな方法を示しています。

UPD。この複雑なシナリオでは、BeanSerializerModifier/BeanDeserializerModifierクラスを見ることができます。考え方は、特定のフィールドのカスタムロジックで一般的なBeanSerializer/BeanDeserializerを変更し、他の処理を行うための基本的な実装を行うことです。後で例を投稿します。

UPD2。私が見る通り、方法の1つはchangePropertiesメソッドを使用し、独自のシリアライザを割り当てることです。

UPD3。カスタムシリアライザの実例で更新されました。逆シリアル化も同様の方法で行うことができます。

UPD4。フルカスタムのシリアライズ/デシリアライズを使用してサンプルを更新しました。

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(); 
     } 
    } 
} 
+0

この情報は実行時にのみ利用できますか?それを逃した。 – udalmik

+0

更新していただきありがとうございます - [BeanPropertyWriter](http://fasterxml.github.com/jackson-databind/javadoc/2.1.0/com/fasterxml/jackson/databind/ser/BeanPropertyWriter.html)には、 withSerializer'メソッドを呼び出します。たぶんあなたは別のバージョンを使用していますか? – assylias

+0

'beanPropertyWriter.assignSerializer(new MyCustomSerializer());'トリックを行いました。 – assylias

関連する問題