View Javadoc

    1   /**
    2    * Copyright (c) 2008-2011, http://www.snakeyaml.org
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *     http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16
    17  package org.yaml.snakeyaml;
    18
    19  import java.io.IOException;
    20  import java.io.InputStream;
    21  import java.io.Reader;
    22  import java.io.StringReader;
    23  import java.io.StringWriter;
    24  import java.io.Writer;
    25  import java.util.ArrayList;
    26  import java.util.Iterator;
    27  import java.util.List;
    28  import java.util.regex.Pattern;
    29
    30  import org.yaml.snakeyaml.DumperOptions.FlowStyle;
    31  import org.yaml.snakeyaml.composer.Composer;
    32  import org.yaml.snakeyaml.constructor.BaseConstructor;
    33  import org.yaml.snakeyaml.constructor.Constructor;
    34  import org.yaml.snakeyaml.emitter.Emitable;
    35  import org.yaml.snakeyaml.emitter.Emitter;
    36  import org.yaml.snakeyaml.error.YAMLException;
    37  import org.yaml.snakeyaml.events.Event;
    38  import org.yaml.snakeyaml.introspector.BeanAccess;
    39  import org.yaml.snakeyaml.nodes.Node;
    40  import org.yaml.snakeyaml.nodes.Tag;
    41  import org.yaml.snakeyaml.parser.Parser;
    42  import org.yaml.snakeyaml.parser.ParserImpl;
    43  import org.yaml.snakeyaml.reader.StreamReader;
    44  import org.yaml.snakeyaml.reader.UnicodeReader;
    45  import org.yaml.snakeyaml.representer.Representer;
    46  import org.yaml.snakeyaml.resolver.Resolver;
    47  import org.yaml.snakeyaml.serializer.Serializer;
    48
    49  /**
    50   * Public YAML interface. Each Thread must have its own instance.
    51   */
    52  public class Yaml {
    53      protected final Resolver resolver;
    54      private String name;
    55      protected BaseConstructor constructor;
    56      protected Representer representer;
    57      protected DumperOptions dumperOptions;
    58      protected LoaderOptions loaderOptions;
    59
    60      /**
    61       * Create Yaml instance. It is safe to create a few instances and use them
    62       * in different Threads.
    63       */
    64      public Yaml() {
    65          this(new Constructor(), new LoaderOptions(), new Representer(), new DumperOptions(),
    66                  new Resolver());
    67      }
    68
    69      public Yaml(LoaderOptions loaderOptions) {
    70          this(new Constructor(), loaderOptions, new Representer(), new DumperOptions(),
    71                  new Resolver());
    72      }
    73
    74      /**
    75       * Create Yaml instance.
    76       *
    77       * @param dumperOptions
    78       *            DumperOptions to configure outgoing objects
    79       */
    80      public Yaml(DumperOptions dumperOptions) {
    81          this(new Constructor(), new Representer(), dumperOptions);
    82      }
    83
    84      /**
    85       * Create Yaml instance. It is safe to create a few instances and use them
    86       * in different Threads.
    87       *
    88       * @param representer
    89       *            Representer to emit outgoing objects
    90       */
    91      public Yaml(Representer representer) {
    92          this(new Constructor(), representer);
    93      }
    94
    95      /**
    96       * Create Yaml instance. It is safe to create a few instances and use them
    97       * in different Threads.
    98       *
    99       * @param constructor
    100      *            BaseConstructor to construct incoming documents
    101      */
    102     public Yaml(BaseConstructor constructor) {
    103         this(constructor, new Representer());
    104     }
    105
    106     /**
    107      * Create Yaml instance. It is safe to create a few instances and use them
    108      * in different Threads.
    109      *
    110      * @param constructor
    111      *            BaseConstructor to construct incoming documents
    112      * @param representer
    113      *            Representer to emit outgoing objects
    114      */
    115     public Yaml(BaseConstructor constructor, Representer representer) {
    116         this(constructor, representer, new DumperOptions());
    117     }
    118
    119     /**
    120      * Create Yaml instance. It is safe to create a few instances and use them
    121      * in different Threads.
    122      *
    123      * @param representer
    124      *            Representer to emit outgoing objects
    125      * @param dumperOptions
    126      *            DumperOptions to configure outgoing objects
    127      */
    128     public Yaml(Representer representer, DumperOptions dumperOptions) {
    129         this(new Constructor(), representer, dumperOptions, new Resolver());
    130     }
    131
    132     /**
    133      * Create Yaml instance. It is safe to create a few instances and use them
    134      * in different Threads.
    135      *
    136      * @param constructor
    137      *            BaseConstructor to construct incoming documents
    138      * @param representer
    139      *            Representer to emit outgoing objects
    140      * @param dumperOptions
    141      *            DumperOptions to configure outgoing objects
    142      */
    143     public Yaml(BaseConstructor constructor, Representer representer, DumperOptions dumperOptions) {
    144         this(constructor, representer, dumperOptions, new Resolver());
    145     }
    146
    147     /**
    148      * Create Yaml instance. It is safe to create a few instances and use them
    149      * in different Threads.
    150      *
    151      * @param constructor
    152      *            BaseConstructor to construct incoming documents
    153      * @param representer
    154      *            Representer to emit outgoing objects
    155      * @param dumperOptions
    156      *            DumperOptions to configure outgoing objects
    157      * @param resolver
    158      *            Resolver to detect implicit type
    159      */
    160     public Yaml(BaseConstructor constructor, Representer representer, DumperOptions dumperOptions,
    161             Resolver resolver) {
    162         this(constructor, new LoaderOptions(), representer, dumperOptions, resolver);
    163     }
    164
    165     /**
    166      * Create Yaml instance. It is safe to create a few instances and use them
    167      * in different Threads.
    168      *
    169      * @param constructor
    170      *            BaseConstructor to construct incoming documents
    171      * @param loaderOptions
    172      *            LoaderOptions to control construction process
    173      * @param representer
    174      *            Representer to emit outgoing objects
    175      * @param dumperOptions
    176      *            DumperOptions to configure outgoing objects
    177      * @param resolver
    178      *            Resolver to detect implicit type
    179      */
    180     public Yaml(BaseConstructor constructor, LoaderOptions loaderOptions, Representer representer,
    181             DumperOptions dumperOptions, Resolver resolver) {
    182         if (!constructor.isExplicitPropertyUtils()) {
    183             constructor.setPropertyUtils(representer.getPropertyUtils());
    184         } else if (!representer.isExplicitPropertyUtils()) {
    185             representer.setPropertyUtils(constructor.getPropertyUtils());
    186         }
    187         this.constructor = constructor;
    188         this.loaderOptions = loaderOptions;
    189         representer.setDefaultFlowStyle(dumperOptions.getDefaultFlowStyle());
    190         representer.setDefaultScalarStyle(dumperOptions.getDefaultScalarStyle());
    191         representer.getPropertyUtils().setAllowReadOnlyProperties(
    192                 dumperOptions.isAllowReadOnlyProperties());
    193         this.representer = representer;
    194         this.dumperOptions = dumperOptions;
    195         this.resolver = resolver;
    196         this.name = "Yaml:" + System.identityHashCode(this);
    197     }
    198
    199     /**
    200      * Serialize a Java object into a YAML String.
    201      *
    202      * @param data
    203      *            Java object to be Serialized to YAML
    204      * @return YAML String
    205      */
    206     public String dump(Object data) {
    207         List<Object> list = new ArrayList<Object>(1);
    208         list.add(data);
    209         return dumpAll(list.iterator());
    210     }
    211
    212     /**
    213      * Produce the corresponding representation tree for a given Object.
    214      *
    215      * @see http://yaml.org/spec/1.1/#id859333
    216      * @param data
    217      *            instance to build the representation tree for
    218      * @return representation tree
    219      */
    220     public Node represent(Object data) {
    221         return representer.represent(data);
    222     }
    223
    224     /**
    225      * Serialize a sequence of Java objects into a YAML String.
    226      *
    227      * @param data
    228      *            Iterator with Objects
    229      * @return YAML String with all the objects in proper sequence
    230      */
    231     public String dumpAll(Iterator<? extends Object> data) {
    232         StringWriter buffer = new StringWriter();
    233         dumpAll(data, buffer);
    234         return buffer.toString();
    235     }
    236
    237     /**
    238      * Serialize a Java object into a YAML stream.
    239      *
    240      * @param data
    241      *            Java object to be serialized to YAML
    242      * @param output
    243      *            stream to write to
    244      */
    245     public void dump(Object data, Writer output) {
    246         List<Object> list = new ArrayList<Object>(1);
    247         list.add(data);
    248         dumpAll(list.iterator(), output);
    249     }
    250
    251     /**
    252      * Serialize a sequence of Java objects into a YAML stream.
    253      *
    254      * @param data
    255      *            Iterator with Objects
    256      * @param output
    257      *            stream to write to
    258      */
    259     @SuppressWarnings("deprecation")
    260     public void dumpAll(Iterator<? extends Object> data, Writer output) {
    261         dumpAll(data, output, dumperOptions.getExplicitRoot());
    262     }
    263
    264     private void dumpAll(Iterator<? extends Object> data, Writer output, Tag rootTag) {
    265         Serializer serializer = new Serializer(new Emitter(output, dumperOptions), resolver,
    266                 dumperOptions, rootTag);
    267         try {
    268             serializer.open();
    269             while (data.hasNext()) {
    270                 Node node = representer.represent(data.next());
    271                 serializer.serialize(node);
    272             }
    273             serializer.close();
    274         } catch (java.io.IOException e) {
    275             throw new YAMLException(e);
    276         }
    277     }
    278
    279     /**
    280      * <p>
    281      * Serialize a Java object into a YAML string. Override the default root tag
    282      * with <code>rootTag</code>.
    283      * </p>
    284      *
    285      * <p>
    286      * This method is similar to <code>Yaml.dump(data)</code> except that the
    287      * root tag for the whole document is replaced with the given tag. This has
    288      * two main uses.
    289      * </p>
    290      *
    291      * <p>
    292      * First, if the root tag is replaced with a standard YAML tag, such as
    293      * <code>Tag.MAP</code>, then the object will be dumped as a map. The root
    294      * tag will appear as <code>!!map</code>, or blank (implicit !!map).
    295      * </p>
    296      *
    297      * <p>
    298      * Second, if the root tag is replaced by a different custom tag, then the
    299      * document appears to be a different type when loaded. For example, if an
    300      * instance of MyClass is dumped with the tag !!YourClass, then it will be
    301      * handled as an instance of YourClass when loaded.
    302      * </p>
    303      *
    304      * @param data
    305      *            Java object to be serialized to YAML
    306      * @param rootTag
    307      *            the tag for the whole YAML document. The tag should be Tag.MAP
    308      *            for a JavaBean to make the tag disappear (to use implicit tag
    309      *            !!map). If <code>null</code> is provided then the standard tag
    310      *            with the full class name is used.
    311      * @param flowStyle
    312      *            flow style for the whole document. See Chapter 10. Collection
    313      *            Styles http://yaml.org/spec/1.1/#id930798. If
    314      *            <code>null</code> is provided then the flow style from
    315      *            DumperOptions is used.
    316      *
    317      * @return YAML String
    318      */
    319     public String dumpAs(Object data, Tag rootTag, FlowStyle flowStyle) {
    320         FlowStyle oldStyle = representer.getDefaultFlowStyle();
    321         if (flowStyle != null) {
    322             representer.setDefaultFlowStyle(flowStyle);
    323         }
    324         List<Object> list = new ArrayList<Object>(1);
    325         list.add(data);
    326         StringWriter buffer = new StringWriter();
    327         dumpAll(list.iterator(), buffer, rootTag);
    328         representer.setDefaultFlowStyle(oldStyle);
    329         return buffer.toString();
    330     }
    331
    332     /**
    333      * <p>
    334      * Serialize a Java object into a YAML string. Override the default root tag
    335      * with <code>Tag.MAP</code>.
    336      * </p>
    337      * <p>
    338      * This method is similar to <code>Yaml.dump(data)</code> except that the
    339      * root tag for the whole document is replaced with <code>Tag.MAP</code> tag
    340      * (implicit !!map).
    341      * </p>
    342      * <p>
    343      * Block Mapping is used as the collection style. See 10.2.2. Block Mappings
    344      * (http://yaml.org/spec/1.1/#id934537)
    345      * </p>
    346      *
    347      * @param data
    348      *            Java object to be serialized to YAML
    349      * @return YAML String
    350      */
    351     public String dumpAsMap(Object data) {
    352         return dumpAs(data, Tag.MAP, FlowStyle.BLOCK);
    353     }
    354
    355     /**
    356      * Serialize the representation tree into Events.
    357      *
    358      * @see http://yaml.org/spec/1.1/#id859333
    359      * @param data
    360      *            representation tree
    361      * @return Event list
    362      */
    363     public List<Event> serialize(Node data) {
    364         SilentEmitter emitter = new SilentEmitter();
    365         @SuppressWarnings("deprecation")
    366         Serializer serializer = new Serializer(emitter, resolver, dumperOptions,
    367                 dumperOptions.getExplicitRoot());
    368         try {
    369             serializer.open();
    370             serializer.serialize(data);
    371             serializer.close();
    372         } catch (java.io.IOException e) {
    373             throw new YAMLException(e);
    374         }
    375         return emitter.getEvents();
    376     }
    377
    378     private class SilentEmitter implements Emitable {
    379         private List<Event> events = new ArrayList<Event>(100);
    380
    381         public List<Event> getEvents() {
    382             return events;
    383         }
    384
    385         public void emit(Event event) throws IOException {
    386             events.add(event);
    387         }
    388     }
    389
    390     /**
    391      * Parse the only YAML document in a String and produce the corresponding
    392      * Java object. (Because the encoding in known BOM is not respected.)
    393      *
    394      * @param yaml
    395      *            YAML data to load from (BOM must not be present)
    396      * @return parsed object
    397      */
    398     public Object load(String yaml) {
    399         return loadFromReader(new StreamReader(yaml), Object.class);
    400     }
    401
    402     /**
    403      * Parse the only YAML document in a stream and produce the corresponding
    404      * Java object.
    405      *
    406      * @param io
    407      *            data to load from (BOM is respected and removed)
    408      * @return parsed object
    409      */
    410     public Object load(InputStream io) {
    411         return loadFromReader(new StreamReader(new UnicodeReader(io)), Object.class);
    412     }
    413
    414     /**
    415      * Parse the only YAML document in a stream and produce the corresponding
    416      * Java object.
    417      *
    418      * @param io
    419      *            data to load from (BOM must not be present)
    420      * @return parsed object
    421      */
    422     public Object load(Reader io) {
    423         return loadFromReader(new StreamReader(io), Object.class);
    424     }
    425
    426     /**
    427      * Parse the only YAML document in a stream and produce the corresponding
    428      * Java object.
    429      *
    430      * @param <T>
    431      *            Class is defined by the second argument
    432      * @param io
    433      *            data to load from (BOM must not be present)
    434      * @param type
    435      *            Class of the object to be created
    436      * @return parsed object
    437      */
    438     @SuppressWarnings("unchecked")
    439     public <T> T loadAs(Reader io, Class<T> type) {
    440         return (T) loadFromReader(new StreamReader(io), type);
    441     }
    442
    443     /**
    444      * Parse the only YAML document in a String and produce the corresponding
    445      * Java object. (Because the encoding in known BOM is not respected.)
    446      *
    447      * @param <T>
    448      *            Class is defined by the second argument
    449      * @param yaml
    450      *            YAML data to load from (BOM must not be present)
    451      * @param type
    452      *            Class of the object to be created
    453      * @return parsed object
    454      */
    455     @SuppressWarnings("unchecked")
    456     public <T> T loadAs(String yaml, Class<T> type) {
    457         return (T) loadFromReader(new StreamReader(yaml), type);
    458     }
    459
    460     /**
    461      * Parse the only YAML document in a stream and produce the corresponding
    462      * Java object.
    463      *
    464      * @param <T>
    465      *            Class is defined by the second argument
    466      * @param input
    467      *            data to load from (BOM is respected and removed)
    468      * @param type
    469      *            Class of the object to be created
    470      * @return parsed object
    471      */
    472     @SuppressWarnings("unchecked")
    473     public <T> T loadAs(InputStream input, Class<T> type) {
    474         return (T) loadFromReader(new StreamReader(new UnicodeReader(input)), type);
    475     }
    476
    477     private Object loadFromReader(StreamReader sreader, Class<?> type) {
    478         Composer composer = new Composer(new ParserImpl(sreader), resolver);
    479         constructor.setComposer(composer);
    480         return constructor.getSingleData(type);
    481     }
    482
    483     /**
    484      * Parse all YAML documents in a String and produce corresponding Java
    485      * objects. The documents are parsed only when the iterator is invoked.
    486      *
    487      * @param yaml
    488      *            YAML data to load from (BOM must not be present)
    489      * @return an iterator over the parsed Java objects in this String in proper
    490      *         sequence
    491      */
    492     public Iterable<Object> loadAll(Reader yaml) {
    493         Composer composer = new Composer(new ParserImpl(new StreamReader(yaml)), resolver);
    494         constructor.setComposer(composer);
    495         Iterator<Object> result = new Iterator<Object>() {
    496             public boolean hasNext() {
    497                 return constructor.checkData();
    498             }
    499
    500             public Object next() {
    501                 return constructor.getData();
    502             }
    503
    504             public void remove() {
    505                 throw new UnsupportedOperationException();
    506             }
    507         };
    508         return new YamlIterable(result);
    509     }
    510
    511     private class YamlIterable implements Iterable<Object> {
    512         private Iterator<Object> iterator;
    513
    514         public YamlIterable(Iterator<Object> iterator) {
    515             this.iterator = iterator;
    516         }
    517
    518         public Iterator<Object> iterator() {
    519             return iterator;
    520         }
    521
    522     }
    523
    524     /**
    525      * Parse all YAML documents in a String and produce corresponding Java
    526      * objects. (Because the encoding in known BOM is not respected.) The
    527      * documents are parsed only when the iterator is invoked.
    528      *
    529      * @param yaml
    530      *            YAML data to load from (BOM must not be present)
    531      * @return an iterator over the parsed Java objects in this String in proper
    532      *         sequence
    533      */
    534     public Iterable<Object> loadAll(String yaml) {
    535         return loadAll(new StringReader(yaml));
    536     }
    537
    538     /**
    539      * Parse all YAML documents in a stream and produce corresponding Java
    540      * objects. The documents are parsed only when the iterator is invoked.
    541      *
    542      * @param yaml
    543      *            YAML data to load from (BOM is respected and ignored)
    544      * @return an iterator over the parsed Java objects in this stream in proper
    545      *         sequence
    546      */
    547     public Iterable<Object> loadAll(InputStream yaml) {
    548         return loadAll(new UnicodeReader(yaml));
    549     }
    550
    551     /**
    552      * Parse the first YAML document in a stream and produce the corresponding
    553      * representation tree. (This is the opposite of the represent() method)
    554      *
    555      * @see http://yaml.org/spec/1.1/#id859333
    556      * @param yaml
    557      *            YAML document
    558      * @return parsed root Node for the specified YAML document
    559      */
    560     public Node compose(Reader yaml) {
    561         Composer composer = new Composer(new ParserImpl(new StreamReader(yaml)), resolver);
    562         constructor.setComposer(composer);
    563         return composer.getSingleNode();
    564     }
    565
    566     /**
    567      * Parse all YAML documents in a stream and produce corresponding
    568      * representation trees.
    569      *
    570      * @see http://yaml.org/spec/1.1/#id859333
    571      * @param yaml
    572      *            stream of YAML documents
    573      * @return parsed root Nodes for all the specified YAML documents
    574      */
    575     public Iterable<Node> composeAll(Reader yaml) {
    576         final Composer composer = new Composer(new ParserImpl(new StreamReader(yaml)), resolver);
    577         constructor.setComposer(composer);
    578         Iterator<Node> result = new Iterator<Node>() {
    579             public boolean hasNext() {
    580                 return composer.checkNode();
    581             }
    582
    583             public Node next() {
    584                 return composer.getNode();
    585             }
    586
    587             public void remove() {
    588                 throw new UnsupportedOperationException();
    589             }
    590         };
    591         return new NodeIterable(result);
    592     }
    593
    594     private class NodeIterable implements Iterable<Node> {
    595         private Iterator<Node> iterator;
    596
    597         public NodeIterable(Iterator<Node> iterator) {
    598             this.iterator = iterator;
    599         }
    600
    601         public Iterator<Node> iterator() {
    602             return iterator;
    603         }
    604     }
    605
    606     /**
    607      * Add an implicit scalar detector. If an implicit scalar value matches the
    608      * given regexp, the corresponding tag is assigned to the scalar.
    609      *
    610      * @deprecated use Tag instead of String
    611      * @param tag
    612      *            tag to assign to the node
    613      * @param regexp
    614      *            regular expression to match against
    615      * @param first
    616      *            a sequence of possible initial characters or null (which means
    617      *            any).
    618      *
    619      */
    620     public void addImplicitResolver(String tag, Pattern regexp, String first) {
    621         addImplicitResolver(new Tag(tag), regexp, first);
    622     }
    623
    624     /**
    625      * Add an implicit scalar detector. If an implicit scalar value matches the
    626      * given regexp, the corresponding tag is assigned to the scalar.
    627      *
    628      * @param tag
    629      *            tag to assign to the node
    630      * @param regexp
    631      *            regular expression to match against
    632      * @param first
    633      *            a sequence of possible initial characters or null (which means
    634      *            any).
    635      */
    636     public void addImplicitResolver(Tag tag, Pattern regexp, String first) {
    637         resolver.addImplicitResolver(tag, regexp, first);
    638     }
    639
    640     @Override
    641     public String toString() {
    642         return name;
    643     }
    644
    645     /**
    646      * Get a meaningful name. It simplifies debugging in a multi-threaded
    647      * environment. If nothing is set explicitly the address of the instance is
    648      * returned.
    649      *
    650      * @return human readable name
    651      */
    652     public String getName() {
    653         return name;
    654     }
    655
    656     /**
    657      * Set a meaningful name to be shown in toString()
    658      *
    659      * @param name
    660      *            human readable name
    661      */
    662     public void setName(String name) {
    663         this.name = name;
    664     }
    665
    666     /**
    667      * Parse a YAML stream and produce parsing events.
    668      *
    669      * @see http://yaml.org/spec/1.1/#id859333
    670      * @param yaml
    671      *            YAML document(s)
    672      * @return parsed events
    673      */
    674     public Iterable<Event> parse(Reader yaml) {
    675         final Parser parser = new ParserImpl(new StreamReader(yaml));
    676         Iterator<Event> result = new Iterator<Event>() {
    677             public boolean hasNext() {
    678                 return parser.peekEvent() != null;
    679             }
    680
    681             public Event next() {
    682                 return parser.getEvent();
    683             }
    684
    685             public void remove() {
    686                 throw new UnsupportedOperationException();
    687             }
    688         };
    689         return new EventIterable(result);
    690     }
    691
    692     private class EventIterable implements Iterable<Event> {
    693         private Iterator<Event> iterator;
    694
    695         public EventIterable(Iterator<Event> iterator) {
    696             this.iterator = iterator;
    697         }
    698
    699         public Iterator<Event> iterator() {
    700             return iterator;
    701         }
    702     }
    703
    704     public void setBeanAccess(BeanAccess beanAccess) {
    705         constructor.getPropertyUtils().setBeanAccess(beanAccess);
    706         representer.getPropertyUtils().setBeanAccess(beanAccess);
    707     }
    708
    709     // deprecated
    710     /**
    711      * @deprecated use with Constructor instead of Loader
    712      */
    713     public Yaml(Loader loader) {
    714         this(loader, new Dumper(new DumperOptions()));
    715     }
    716
    717     /**
    718      * @deprecated use with Constructor instead of Loader
    719      */
    720     public Yaml(Loader loader, Dumper dumper) {
    721         this(loader, dumper, new Resolver());
    722     }
    723
    724     /**
    725      * @deprecated use with Constructor instead of Loader
    726      */
    727     public Yaml(Loader loader, Dumper dumper, Resolver resolver) {
    728         this(loader.constructor, dumper.representer, dumper.options, resolver);
    729     }
    730
    731     /**
    732      * Create Yaml instance. It is safe to create a few instances and use them
    733      * in different Threads.
    734      *
    735      * @param dumper
    736      *            Dumper to emit outgoing objects
    737      */
    738     @SuppressWarnings("deprecation")
    739     public Yaml(Dumper dumper) {
    740         this(new Constructor(), dumper.representer, dumper.options);
    741     }
    742 }