2016-11-21 9 views
2

私はMap<String, Integer>の周りに単純なラッパーで、私はSnakeYAMLでYAMLにダンプしています。一例として、SnakeYAMLでシングル子Beanを折りたたみます

:現在

class Flags { 
    private final Map<String, Boolean> _flags = new HashMap<>(); 
    Boolean get(String flag) { 
     return _flags.containsKey(flag) ? _flags.get(flag) : false; 
    } 
    boolean put(String flag, Boolean value) { 
     return _flags.put(flag, value); 
    } 
} 

、私が正しく、このクラスをダンプするDumperOptionsallowReadOnlyProperties = trueとし、FIELDBeanAccessを使用しています。含まれているクラスに入れたとき、私はこのようなdumpAsMap YAMLを得る:

flags: 
    _flags: {} 

は、私が代わりにこれをダンプするSnakeYAMLを取得したいと思います:

flags: {} 

は、どのように私はシングルのこの平坦化を達成することができます要素層?内部変数はプライベートであり、ラッピング型はラップされた型として効果的に動作するはずですので、ラップ型をラップされた型と同じようにシリアル化する必要があります。

基本的には、ラッピングタイプをラップされたタイプのようにシリアル化するようにします。ラップされた変数の外でこのクラスでシリアライズする必要がある他の変数はありません。私はラッピング型の型宣言を変更することはできますが、ラッピング型は使用するために残す必要があります。実行可能な再生の場合の

完全なソース:

import org.yaml.snakeyaml.*; 
import org.yaml.snakeyaml.introspector.*; 
import java.util.*; 

public class Example { 
    private final Flags flags = new Flags(); 
    public Flags getFlags() { return flags; } 

    public static void main(String[] args) { 
     DumperOptions options = new DumperOptions(); 
     options.setAllowReadOnlyProperties(true); 
     Yaml yaml = new Yaml(options); 
     yaml.setBeanAccess(BeanAccess.FIELD); 
     System.out.println(yaml.dumpAsMap(new Example())); 
    } 
} 

class Flags { 
    private final Map<String, Boolean> _flags = new HashMap<>(); 
    Boolean get(String flag) { 
     return _flags.containsKey(flag) ? _flags.get(flag) : false; 
    } 
    boolean put(String flag, Boolean value) { 
     return _flags.put(flag, value); 
    } 
} 

答えて

1

このような何かは(コードをテストしていない)に動作可能性があります

class FlagsRepresenter extends Representer { 
    public FlagsRepresenter() { 
     this.representers.put(Flags.class, new RepresentFlags()); 
    } 

    private class RepresentFlags implements Represent { 
     public Node representData(Object data) { 
      // going the hacky, painful way of accessing a private field here. 
      // YMMV. 
      try { 
       final Field f = data.getClass().getDeclaredField("_flags"); 
       f.setAccessible(true); 
       final Map<String, Boolean> inner = 
         (Map<String, Boolean>) f.get(data); 
       return representMapping(Tag.MAP, inner, null); 
      } catch (final Exception ignored) { 
       // will not occur as long as field _flags exists and has the 
       // expected type. 
       return null; 
      } 

     } 
    } 
} 

はこのようにそれを使用します。

Yaml yaml = new Yaml(new FlagsRepresenter(), new DumperOptions()); 
+0

Iラップされたタイプごとにカスタムの 'Represent'を書かなくてもこれが可能だったと思うが、これは現時点で最良の方法だと思われる。デシリアライゼーションに関するコメントはこれを完璧な答えにするでしょう。 – CAD97

+0

(テスト済みで動作します) – CAD97

+1

デシリアライズの場合、[documentation](https://bitbucket.org/asomov/snakeyaml/wiki/Documentation#markdown-header-constructors-representers-resolvers)のサンプルコードを簡単に変更できます。私は表現のためにやったように。 – flyx