001package org.apache.juneau.marshaller; 002// *************************************************************************************************************************** 003// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 004// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 005// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 006// * with the License. You may obtain a copy of the License at * 007// * * 008// * http://www.apache.org/licenses/LICENSE-2.0 * 009// * * 010// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 011// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 012// * specific language governing permissions and limitations under the License. * 013// *************************************************************************************************************************** 014 015import java.io.*; 016import java.lang.reflect.*; 017import java.nio.charset.*; 018 019import org.apache.juneau.*; 020import org.apache.juneau.parser.*; 021import org.apache.juneau.parser.ParseException; 022import org.apache.juneau.serializer.*; 023 024/** 025 * Top-level class for a pairing of a {@link Serializer} and {@link Parser} into a single class with convenience read/write methods. 026 * 027 * <p> 028 * The general idea is to combine a single serializer and parser inside a simplified API for reading and writing POJOs. 029 * 030 * <h5 class='figure'>Examples:</h5> 031 * <p class='bjava'> 032 * <jc>// Using instance.</jc> 033 * Marshaller <jv>json</jv> = <jk>new</jk> Json(); 034 * MyPojo <jv>myPojo</jv> = <jv>json</jv>.read(<jv>string</jv>, MyPojo.<jk>class</jk>); 035 * String <jv>string</jv> = <jv>json</jv>.write(<jv>myPojo</jv>); 036 * </p> 037 * <p class='bjava'> 038 * <jc>// Using DEFAULT instance.</jc> 039 * MyPojo <jv>myPojo</jv> = Json.<jsf>DEFAULT</jsf>.read(<jv>string</jv>, MyPojo.<jk>class</jk>); 040 * String <jv>string</jv> = Json.<jsf>DEFAULT</jsf>.write(<jv>myPojo</jv>); 041 * </p> 042 * 043 * <h5 class='section'>See Also:</h5><ul> 044 * <li class='link'><a class="doclink" href="../../../../index.html#jm.Marshallers">Marshallers</a> 045 * </ul> 046 */ 047public abstract class Marshaller { 048 049 //----------------------------------------------------------------------------------------------------------------- 050 // Instance 051 //----------------------------------------------------------------------------------------------------------------- 052 053 private final Serializer s; 054 private final Parser p; 055 056 /** 057 * Constructor. 058 * 059 * @param s 060 * The serializer to use for serializing output. 061 * <br>Must not be <jk>null</jk>. 062 * @param p 063 * The parser to use for parsing input. 064 * <br>Must not be <jk>null</jk>. 065 */ 066 protected Marshaller(Serializer s, Parser p) { 067 this.s = s; 068 this.p = p; 069 } 070 071 /** 072 * Returns the serializer associated with this marshaller. 073 * 074 * @return The serializer associated with this marshaller. 075 */ 076 public Serializer getSerializer() { 077 return s; 078 } 079 080 /** 081 * Returns the parser associated with this marshaller. 082 * 083 * @return The parser associated with this marshaller. 084 */ 085 public Parser getParser() { 086 return p; 087 } 088 089 /** 090 * Serializes a POJO to the specified output stream or writer. 091 * 092 * <p> 093 * Equivalent to calling <c>serializer.createSession().serialize(o, output);</c> 094 * 095 * @param object The object to serialize. 096 * @param output 097 * The output object. 098 * <br>Character-based serializers can handle the following output class types: 099 * <ul> 100 * <li>{@link Writer} 101 * <li>{@link OutputStream} - Output will be written as UTF-8 encoded stream. 102 * <li>{@link File} - Output will be written as system-default encoded stream. 103 * <li>{@link StringBuilder} - Output will be written to the specified string builder. 104 * </ul> 105 * <br>Stream-based serializers can handle the following output class types: 106 * <ul> 107 * <li>{@link OutputStream} 108 * <li>{@link File} 109 * </ul> 110 * @throws SerializeException If a problem occurred trying to convert the output. 111 * @throws IOException Thrown by underlying stream. 112 */ 113 public final void write(Object object, Object output) throws SerializeException, IOException { 114 s.serialize(object, output); 115 } 116 117 /** 118 * Parses input into the specified object type. 119 * 120 * <p> 121 * The type can be a simple type (e.g. beans, strings, numbers) or parameterized type (collections/maps). 122 * 123 * <h5 class='section'>Examples:</h5> 124 * <p class='bjava'> 125 * Marshaller <jv>marshaller</jv> = Json.<jsf>DEFAULT</jsf>; 126 * 127 * <jc>// Parse into a linked-list of strings.</jc> 128 * List <jv>list1</jv> = <jv>marshaller</jv> .read(<jv>json</jv>, LinkedList.<jk>class</jk>, String.<jk>class</jk>); 129 * 130 * <jc>// Parse into a linked-list of beans.</jc> 131 * List <jv>list2</jv> = <jv>marshaller</jv> .read(<jv>json</jv>, LinkedList.<jk>class</jk>, MyBean.<jk>class</jk>); 132 * 133 * <jc>// Parse into a linked-list of linked-lists of strings.</jc> 134 * List <jv>list3</jv> = <jv>marshaller</jv> .read(<jv>json</jv>, LinkedList.<jk>class</jk>, LinkedList.<jk>class</jk>, String.<jk>class</jk>); 135 * 136 * <jc>// Parse into a map of string keys/values.</jc> 137 * Map <jv>map1</jv> = <jv>marshaller</jv> .read(<jv>json</jv>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>); 138 * 139 * <jc>// Parse into a map containing string keys and values of lists containing beans.</jc> 140 * Map <jv>map2</jv> = <jv>marshaller</jv> .read(<jv>json</jv>, TreeMap.<jk>class</jk>, String.<jk>class</jk>, List.<jk>class</jk>, MyBean.<jk>class</jk>); 141 * </p> 142 * 143 * <p> 144 * <c>Collection</c> classes are assumed to be followed by zero or one objects indicating the element type. 145 * 146 * <p> 147 * <c>Map</c> classes are assumed to be followed by zero or two meta objects indicating the key and value types. 148 * 149 * <p> 150 * The array can be arbitrarily long to indicate arbitrarily complex data structures. 151 * 152 * <h5 class='section'>Notes:</h5><ul> 153 * <li class='note'> 154 * Use the {@link #read(Object, Class)} method instead if you don't need a parameterized map/collection. 155 * </ul> 156 * 157 * @param <T> The class type of the object to create. 158 * @param input 159 * The input. 160 * <br>Character-based parsers can handle the following input class types: 161 * <ul> 162 * <li><jk>null</jk> 163 * <li>{@link Reader} 164 * <li>{@link CharSequence} 165 * <li>{@link InputStream} containing UTF-8 encoded text (or charset defined by 166 * {@link org.apache.juneau.parser.ReaderParser.Builder#streamCharset(Charset)} property value). 167 * <li><code><jk>byte</jk>[]</code> containing UTF-8 encoded text (or charset defined by 168 * {@link org.apache.juneau.parser.ReaderParser.Builder#streamCharset(Charset)} property value). 169 * <li>{@link File} containing system encoded text (or charset defined by 170 * {@link org.apache.juneau.parser.ReaderParser.Builder#fileCharset(Charset)} property value). 171 * </ul> 172 * <br>Stream-based parsers can handle the following input class types: 173 * <ul> 174 * <li><jk>null</jk> 175 * <li>{@link InputStream} 176 * <li><code><jk>byte</jk>[]</code> 177 * <li>{@link File} 178 * <li>{@link CharSequence} containing encoded bytes according to the {@link org.apache.juneau.parser.InputStreamParser.Builder#binaryFormat(BinaryFormat)} setting. 179 * </ul> 180 * @param type 181 * The object type to create. 182 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 183 * @param args 184 * The type arguments of the class if it's a collection or map. 185 * <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} 186 * <br>Ignored if the main type is not a map or collection. 187 * @return The parsed object. 188 * @throws ParseException Malformed input encountered. 189 * @throws IOException Thrown by underlying stream. 190 * @see BeanSession#getClassMeta(Type,Type...) for argument syntax for maps and collections. 191 */ 192 public final <T> T read(Object input, Type type, Type...args) throws ParseException, IOException { 193 return p.parse(input, type, args); 194 } 195 196 /** 197 * Same as {@link #read(Object, Type, Type...)} except optimized for a non-parameterized class. 198 * 199 * <p> 200 * This is the preferred parse method for simple types since you don't need to cast the results. 201 * 202 * <h5 class='section'>Examples:</h5> 203 * <p class='bjava'> 204 * Marshaller <jv>marshaller</jv> = Json.<jsf>DEFAULT</jsf>; 205 * 206 * <jc>// Parse into a string.</jc> 207 * String <jv>string</jv> = <jv>marshaller</jv> .read(<jv>json</jv>, String.<jk>class</jk>); 208 * 209 * <jc>// Parse into a bean.</jc> 210 * MyBean <jv>bean</jv> = <jv>marshaller</jv> .read(<jv>json</jv>, MyBean.<jk>class</jk>); 211 * 212 * <jc>// Parse into a bean array.</jc> 213 * MyBean[] <jv>beanArray</jv> = <jv>marshaller</jv> .read(<jv>json</jv>, MyBean[].<jk>class</jk>); 214 * 215 * <jc>// Parse into a linked-list of objects.</jc> 216 * List <jv>list</jv> = <jv>marshaller</jv> .read(<jv>json</jv>, LinkedList.<jk>class</jk>); 217 * 218 * <jc>// Parse into a map of object keys/values.</jc> 219 * Map <jv>map</jv> = <jv>marshaller</jv> .read(<jv>json</jv>, TreeMap.<jk>class</jk>); 220 * </p> 221 * 222 * @param <T> The class type of the object being created. 223 * @param input 224 * The input. 225 * <br>Character-based parsers can handle the following input class types: 226 * <ul> 227 * <li><jk>null</jk> 228 * <li>{@link Reader} 229 * <li>{@link CharSequence} 230 * <li>{@link InputStream} containing UTF-8 encoded text (or charset defined by 231 * {@link org.apache.juneau.parser.ReaderParser.Builder#streamCharset(Charset)} property value). 232 * <li><code><jk>byte</jk>[]</code> containing UTF-8 encoded text (or charset defined by 233 * {@link org.apache.juneau.parser.ReaderParser.Builder#streamCharset(Charset)} property value). 234 * <li>{@link File} containing system encoded text (or charset defined by 235 * {@link org.apache.juneau.parser.ReaderParser.Builder#fileCharset(Charset)} property value). 236 * </ul> 237 * <br>Stream-based parsers can handle the following input class types: 238 * <ul> 239 * <li><jk>null</jk> 240 * <li>{@link InputStream} 241 * <li><code><jk>byte</jk>[]</code> 242 * <li>{@link File} 243 * <li>{@link CharSequence} containing encoded bytes according to the {@link org.apache.juneau.parser.InputStreamParser.Builder#binaryFormat(BinaryFormat)} setting. 244 * </ul> 245 * @param type The object type to create. 246 * @return The parsed object. 247 * @throws ParseException Malformed input encountered. 248 * @throws IOException Thrown by underlying stream. 249 */ 250 public final <T> T read(Object input, Class<T> type) throws ParseException, IOException { 251 return p.parse(input, type); 252 } 253}