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.hjson.*; 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 HjsonSerializer} and {@link HjsonParser} 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 * Hjson <jv>hjson</jv> = <jk>new</jk> Hjson(); 036 * MyPojo <jv>myPojo</jv> = <jv>hjson</jv>.read(<jv>string</jv>, MyPojo.<jk>class</jk>); 037 * String <jv>string</jv> = <jv>hjson</jv>.write(<jv>myPojo</jv>); 038 * </p> 039 * <p class='bjava'> 040 * <jc>// Using DEFAULT instance.</jc> 041 * MyPojo <jv>myPojo</jv> = Hjson.<jsf>DEFAULT</jsf>.read(<jv>string</jv>, MyPojo.<jk>class</jk>); 042 * String <jv>string</jv> = Hjson.<jsf>DEFAULT</jsf>.write(<jv>myPojo</jv>); 043 * </p> 044 * 045 * <h5 class='figure'>Example output - readable mode (Map of name/age):</h5> 046 * <p class='bjson'> 047 * { 048 * name: Alice 049 * age: 30 050 * } 051 * </p> 052 * 053 * <h5 class='figure'>Example output - compact mode ({@link HjsonC}):</h5> 054 * <p class='bjson'> 055 * {name:Alice,age:30} 056 * </p> 057 * 058 * <p class='bjava'> 059 * <jc>// Using static shortcuts.</jc> 060 * MyPojo <jv>myPojo</jv> = Hjson.<jsm>to</jsm>(<jv>string</jv>, MyPojo.<jk>class</jk>); 061 * String <jv>string</jv> = Hjson.<jsm>of</jsm>(<jv>myPojo</jv>); 062 * </p> 063 * 064 * <h5 class='section'>See Also:</h5><ul> 065 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshallers">Marshallers</a> 066 * <li class='link'><a class="doclink" href="https://hjson.github.io/syntax.html">Hjson Specification</a> 067 * </ul> 068 */ 069@SuppressWarnings({ 070 "resource" // Cursor shortcut methods return Closeables owned by the caller; Eclipse JDT @Owning warning is by design. 071}) 072public class Hjson extends CharMarshaller { 073 074 /** Default reusable instance. */ 075 public static final Hjson DEFAULT = new Hjson(); 076 077 /** 078 * Serializes a POJO to a <c>String</c> using the {@link #DEFAULT} marshaller. 079 * 080 * <p> 081 * A shortcut for calling <c><jsf>DEFAULT</jsf>.write(<jv>object</jv>)</c>. 082 * 083 * @param object The object to serialize. 084 * @return The serialized object. 085 * @throws SerializeException If a problem occurred trying to convert the output. 086 */ 087 public static String of(Object object) throws SerializeException { 088 return DEFAULT.write(object); 089 } 090 091 /** 092 * Parses an input into the specified object type using the {@link #DEFAULT} marshaller. 093 * 094 * <p> 095 * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>)</c>. 096 * 097 * @param <T> The class type of the object being created. 098 * @param input The input. 099 * @param type The object type to create. 100 * @return The parsed object. 101 * @throws ParseException Malformed input encountered. 102 */ 103 public static <T> T to(String input, Class<T> type) throws ParseException { 104 return DEFAULT.read(input, type); 105 } 106 107 /** 108 * Parses an input into the specified parameterized object type using the {@link #DEFAULT} marshaller. 109 * 110 * <p> 111 * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>, <jv>args</jv>)</c>. 112 * 113 * @param <T> The class type of the object to create. 114 * @param input The input. 115 * @param type The object type to create. 116 * @param args The type arguments of the class if it's a collection or map. 117 * @return The parsed object. 118 * @throws ParseException Malformed input encountered. 119 */ 120 public static <T> T to(String input, Type type, Type... args) throws ParseException { 121 return DEFAULT.read(input, type, args); 122 } 123 124 /** 125 * Parses the contents of a {@link Reader} into the specified object type using the {@link #DEFAULT} marshaller. 126 * 127 * <p> 128 * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>)</c> that catches any 129 * {@link IOException} from the underlying stream and rethrows it as an unchecked {@link ParseException}, so the 130 * caller is not burdened with a checked exception. 131 * 132 * @param <T> The class type of the object being created. 133 * @param input The input reader. 134 * @param type The object type to create. 135 * @return The parsed object. 136 * @throws ParseException Malformed input encountered or an I/O error occurred on the underlying stream. 137 */ 138 public static <T> T to(Reader input, Class<T> type) throws ParseException { 139 try { 140 return DEFAULT.read(input, type); 141 } catch (IOException e) { 142 throw new ParseException(e); 143 } 144 } 145 146 /** 147 * Parses the contents of a {@link Reader} into the specified parameterized object type using the {@link #DEFAULT} marshaller. 148 * 149 * <p> 150 * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>, <jv>args</jv>)</c> that catches any 151 * {@link IOException} from the underlying stream and rethrows it as an unchecked {@link ParseException}, so the 152 * caller is not burdened with a checked exception. 153 * 154 * @param <T> The class type of the object to create. 155 * @param input The input reader. 156 * @param type The object type to create. 157 * @param args The type arguments of the class if it's a collection or map. 158 * @return The parsed object. 159 * @throws ParseException Malformed input encountered or an I/O error occurred on the underlying stream. 160 */ 161 public static <T> T to(Reader input, Type type, Type... args) throws ParseException { 162 try { 163 return DEFAULT.read(input, type, args); 164 } catch (IOException e) { 165 throw new ParseException(e); 166 } 167 } 168 169 /** 170 * Serializes a POJO to the specified {@link Writer} using the {@link #DEFAULT} marshaller. 171 * 172 * <p> 173 * A shortcut for calling <c><jsf>DEFAULT</jsf>.write(<jv>object</jv>, <jv>output</jv>)</c> that catches any 174 * {@link IOException} from the underlying stream and rethrows it as an unchecked {@link SerializeException}, so the 175 * caller is not burdened with a checked exception. 176 * 177 * @param object The object to serialize. 178 * @param output The writer to serialize to. 179 * @throws SerializeException If a problem occurred trying to convert the output or an I/O error occurred on the underlying stream. 180 */ 181 public static void of(Object object, Writer output) throws SerializeException { 182 try { 183 DEFAULT.write(object, output); 184 } catch (IOException e) { 185 throw new SerializeException(e); 186 } 187 } 188 189 /** 190 * Opens a low-level {@link RecordReader} cursor over the specified input using the {@link #DEFAULT} marshaller. 191 * 192 * <p> 193 * A shortcut for calling <c><jsf>DEFAULT</jsf>.readRecords(<jv>input</jv>)</c>. 194 * 195 * @param input The input. 196 * @return A new {@link RecordReader}. 197 * @throws IOException If a problem occurred opening the underlying input. 198 */ 199 public static RecordReader toRecords(Object input) throws IOException { 200 return DEFAULT.readRecords(input); 201 } 202 203 /** 204 * Opens a low-level {@link RecordWriter} cursor over the specified output using the {@link #DEFAULT} marshaller. 205 * 206 * <p> 207 * A shortcut for calling <c><jsf>DEFAULT</jsf>.writeRecords(<jv>output</jv>)</c>. 208 * 209 * @param output The output. 210 * @return A new {@link RecordWriter}. 211 * @throws IOException If a problem occurred opening the underlying output. 212 */ 213 public static RecordWriter ofRecords(Object output) throws IOException { 214 return DEFAULT.writeRecords(output); 215 } 216 217 /** 218 * Constructor. 219 * 220 * <p> 221 * Uses {@link HjsonSerializer#DEFAULT} and {@link HjsonParser#DEFAULT}. 222 */ 223 public Hjson() { 224 this(HjsonSerializer.DEFAULT, HjsonParser.DEFAULT); 225 } 226 227 /** 228 * Constructor. 229 * 230 * @param s The serializer to use. 231 * @param p The parser to use. 232 */ 233 public Hjson(HjsonSerializer s, HjsonParser p) { 234 super(s, p); 235 } 236}