001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.marshall.marshaller; 018 019import org.apache.juneau.marshall.yaml.*; 020import java.io.*; 021import java.lang.reflect.*; 022import org.apache.juneau.marshall.parser.*; 023import org.apache.juneau.marshall.serializer.*; 024import org.apache.juneau.marshall.stream.*; 025 026/** 027 * A pairing of a {@link YamlSerializer} and {@link YamlParser} into a single class with convenience to/of methods. 028 * 029 * <p> 030 * The general idea is to combine a single serializer and parser inside a simplified API for serializing and parsing POJOs. 031 * 032 * <h5 class='figure'>Examples:</h5> 033 * <p class='bjava'> 034 * <jc>// Using instance.</jc> 035 * Yaml <jv>yaml</jv> = <jk>new</jk> Yaml(); 036 * MyPojo <jv>myPojo</jv> = <jv>yaml</jv>.read(<jv>string</jv>, MyPojo.<jk>class</jk>); 037 * String <jv>string</jv> = <jv>yaml</jv>.write(<jv>myPojo</jv>); 038 * </p> 039 * <p class='bjava'> 040 * <jc>// Using DEFAULT instance.</jc> 041 * MyPojo <jv>myPojo</jv> = Yaml.<jsf>DEFAULT</jsf>.read(<jv>string</jv>, MyPojo.<jk>class</jk>); 042 * String <jv>string</jv> = Yaml.<jsf>DEFAULT</jsf>.write(<jv>myPojo</jv>); 043 * </p> 044 * 045 * <h5 class='figure'>Example output (Map of name/age):</h5> 046 * <p class='bcode'> 047 * name: Alice 048 * age: 30 049 * </p> 050 * 051 * <h5 class='figure'>Complex (nested object + array):</h5> 052 * <p class='bcode'> 053 * name: Alice 054 * age: 30 055 * address: 056 * street: 123 Main St 057 * city: Boston 058 * state: MA 059 * tags: 060 * - a 061 * - b 062 * - c 063 * </p> 064 * 065 * <p class='bjava'> 066 * <jc>// Using static shortcuts.</jc> 067 * MyPojo <jv>myPojo</jv> = Yaml.<jsm>to</jsm>(<jv>string</jv>, MyPojo.<jk>class</jk>); 068 * String <jv>string</jv> = Yaml.<jsm>of</jsm>(<jv>myPojo</jv>); 069 * </p> 070 * 071 * <h5 class='section'>See Also:</h5><ul> 072 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshallers">Marshallers</a> 073 * </ul> 074 */ 075@SuppressWarnings({ 076 "resource" // Cursor shortcut methods return Closeables owned by the caller; Eclipse JDT @Owning warning is by design. 077}) 078public class Yaml extends CharMarshaller { 079 080 /** 081 * Default reusable instance. 082 */ 083 public static final Yaml DEFAULT = new Yaml(); 084 085 /** 086 * Serializes a POJO to a <c>String</c> using the {@link #DEFAULT} marshaller. 087 * 088 * <p> 089 * A shortcut for calling <c><jsf>DEFAULT</jsf>.write(<jv>object</jv>)</c>. 090 * 091 * @param object The object to serialize. 092 * @return The serialized object. 093 * @throws SerializeException If a problem occurred trying to convert the output. 094 */ 095 public static String of(Object object) throws SerializeException { 096 return DEFAULT.write(object); 097 } 098 099 /** 100 * Parses an input into the specified object type using the {@link #DEFAULT} marshaller. 101 * 102 * <p> 103 * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>)</c>. 104 * 105 * @param <T> The class type of the object being created. 106 * @param input The input. 107 * @param type The object type to create. 108 * @return The parsed object. 109 * @throws ParseException Malformed input encountered. 110 */ 111 public static <T> T to(String input, Class<T> type) throws ParseException { 112 return DEFAULT.read(input, type); 113 } 114 115 /** 116 * Parses an input into the specified parameterized object type using the {@link #DEFAULT} marshaller. 117 * 118 * <p> 119 * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>, <jv>args</jv>)</c>. 120 * 121 * @param <T> The class type of the object to create. 122 * @param input The input. 123 * @param type The object type to create. 124 * @param args The type arguments of the class if it's a collection or map. 125 * @return The parsed object. 126 * @throws ParseException Malformed input encountered. 127 */ 128 public static <T> T to(String input, Type type, Type... args) throws ParseException { 129 return DEFAULT.read(input, type, args); 130 } 131 132 /** 133 * Parses the contents of a {@link Reader} into the specified object type using the {@link #DEFAULT} marshaller. 134 * 135 * <p> 136 * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>)</c> that catches any 137 * {@link IOException} from the underlying stream and rethrows it as an unchecked {@link ParseException}, so the 138 * caller is not burdened with a checked exception. 139 * 140 * @param <T> The class type of the object being created. 141 * @param input The input reader. 142 * @param type The object type to create. 143 * @return The parsed object. 144 * @throws ParseException Malformed input encountered or an I/O error occurred on the underlying stream. 145 */ 146 public static <T> T to(Reader input, Class<T> type) throws ParseException { 147 try { 148 return DEFAULT.read(input, type); 149 } catch (IOException e) { 150 throw new ParseException(e); 151 } 152 } 153 154 /** 155 * Parses the contents of a {@link Reader} into the specified parameterized object type using the {@link #DEFAULT} marshaller. 156 * 157 * <p> 158 * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>, <jv>args</jv>)</c> that catches any 159 * {@link IOException} from the underlying stream and rethrows it as an unchecked {@link ParseException}, so the 160 * caller is not burdened with a checked exception. 161 * 162 * @param <T> The class type of the object to create. 163 * @param input The input reader. 164 * @param type The object type to create. 165 * @param args The type arguments of the class if it's a collection or map. 166 * @return The parsed object. 167 * @throws ParseException Malformed input encountered or an I/O error occurred on the underlying stream. 168 */ 169 public static <T> T to(Reader input, Type type, Type... args) throws ParseException { 170 try { 171 return DEFAULT.read(input, type, args); 172 } catch (IOException e) { 173 throw new ParseException(e); 174 } 175 } 176 177 /** 178 * Serializes a POJO to the specified {@link Writer} using the {@link #DEFAULT} marshaller. 179 * 180 * <p> 181 * A shortcut for calling <c><jsf>DEFAULT</jsf>.write(<jv>object</jv>, <jv>output</jv>)</c> that catches any 182 * {@link IOException} from the underlying stream and rethrows it as an unchecked {@link SerializeException}, so the 183 * caller is not burdened with a checked exception. 184 * 185 * @param object The object to serialize. 186 * @param output The writer to serialize to. 187 * @throws SerializeException If a problem occurred trying to convert the output or an I/O error occurred on the underlying stream. 188 */ 189 public static void of(Object object, Writer output) throws SerializeException { 190 try { 191 DEFAULT.write(object, output); 192 } catch (IOException e) { 193 throw new SerializeException(e); 194 } 195 } 196 197 /** 198 * Opens a low-level {@link RecordReader} cursor over the specified input using the {@link #DEFAULT} marshaller. 199 * 200 * <p> 201 * A shortcut for calling <c><jsf>DEFAULT</jsf>.readRecords(<jv>input</jv>)</c>. 202 * 203 * @param input The input. 204 * @return A new {@link RecordReader}. 205 * @throws IOException If a problem occurred opening the underlying input. 206 */ 207 public static RecordReader toRecords(Object input) throws IOException { 208 return DEFAULT.readRecords(input); 209 } 210 211 /** 212 * Opens a low-level {@link RecordWriter} cursor over the specified output using the {@link #DEFAULT} marshaller. 213 * 214 * <p> 215 * A shortcut for calling <c><jsf>DEFAULT</jsf>.writeRecords(<jv>output</jv>)</c>. 216 * 217 * @param output The output. 218 * @return A new {@link RecordWriter}. 219 * @throws IOException If a problem occurred opening the underlying output. 220 */ 221 public static RecordWriter ofRecords(Object output) throws IOException { 222 return DEFAULT.writeRecords(output); 223 } 224 225 /** 226 * Opens a {@link RecordReader} that yields each element of a top-level wire array using the {@link #DEFAULT} marshaller. 227 * 228 * <p> 229 * A shortcut for calling <c><jsf>DEFAULT</jsf>.readArrayRecords(<jv>input</jv>)</c>. 230 * 231 * @param input The input. 232 * @return A new {@link RecordReader}. 233 * @throws IOException If a problem occurred opening the underlying input. 234 */ 235 public static RecordReader toArrayRecords(Object input) throws IOException { 236 return DEFAULT.readArrayRecords(input); 237 } 238 239 /** 240 * Opens a {@link RecordWriter} that wraps each written value as one element of a top-level wire array using the {@link #DEFAULT} marshaller. 241 * 242 * <p> 243 * A shortcut for calling <c><jsf>DEFAULT</jsf>.writeArrayRecords(<jv>output</jv>)</c>. 244 * 245 * @param output The output. 246 * @return A new {@link RecordWriter}. 247 * @throws IOException If a problem occurred opening the underlying output. 248 */ 249 public static RecordWriter ofArrayRecords(Object output) throws IOException { 250 return DEFAULT.writeArrayRecords(output); 251 } 252 253 /** 254 * Constructor. 255 * 256 * <p> 257 * Uses {@link YamlSerializer#DEFAULT} and {@link YamlParser#DEFAULT}. 258 */ 259 public Yaml() { 260 this(YamlSerializer.DEFAULT, YamlParser.DEFAULT); 261 } 262 263 /** 264 * Constructor. 265 * 266 * @param s 267 * The serializer to use for serializing output. 268 * <br>Must not be <jk>null</jk>. 269 * @param p 270 * The parser to use for parsing input. 271 * <br>Must not be <jk>null</jk>. 272 */ 273 public Yaml(YamlSerializer s, YamlParser p) { 274 super(s, p); 275 } 276}