1 package de.juplo.jackson;
4 import com.fasterxml.jackson.core.JsonLocation;
5 import com.fasterxml.jackson.core.JsonParser;
6 import com.fasterxml.jackson.core.JsonToken;
7 import java.io.IOException;
8 import java.util.Collections;
9 import java.util.Iterator;
10 import java.util.LinkedHashMap;
11 import java.util.LinkedList;
12 import java.util.List;
14 import java.util.Map.Entry;
15 import java.util.NoSuchElementException;
16 import java.util.Spliterator;
17 import static java.util.Spliterator.IMMUTABLE;
18 import java.util.Spliterators;
19 import java.util.function.Consumer;
20 import java.util.stream.Stream;
21 import java.util.stream.StreamSupport;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
31 public abstract class SimpleMapper
33 private static final Logger LOG =
34 LoggerFactory.getLogger(SimpleMapper.class);
37 public static Spliterator<Object> getArraySpliterator(final JsonParser parser)
41 JsonToken token = parser.nextToken();
45 LOG.warn("empty input");
46 return Spliterators.emptySpliterator();
49 if (!JsonToken.START_ARRAY.equals(token))
50 fail(parser, "The root-element must be an array!");
52 return new Spliterator<Object>()
55 public boolean tryAdvance(Consumer<? super Object> action)
59 JsonToken token = parser.nextToken();
61 fail(parser, "Unexpected end of data!");
62 if (JsonToken.END_ARRAY.equals(token))
64 if (parser.nextToken() != null)
65 fail(parser, "unexpected data after parsed array");
68 action.accept(convertInternal(parser));
73 throw new IllegalArgumentException(e);
78 public Spliterator<Object> trySplit()
84 public long estimateSize()
86 return Long.MAX_VALUE;
90 public int characteristics()
97 public static Stream<Object> getArrayStream(final JsonParser parser)
101 return StreamSupport.stream(getArraySpliterator(parser), false);
104 public static Iterator<Object> getArrayIterator(final JsonParser parser)
108 Spliterator<Object> spliterator = getArraySpliterator(parser);
109 return new Iterator<Object>()
111 private Object next = null;
115 public boolean hasNext()
120 return spliterator.tryAdvance(new Consumer<Object>()
123 public void accept(Object o)
133 if (next == null && !hasNext())
134 throw new NoSuchElementException();
143 public static Spliterator<Entry<String, Object>> getObjectSpliterator(final JsonParser parser)
147 JsonToken token = parser.nextToken();
151 LOG.warn("empty input");
152 return Spliterators.emptySpliterator();
155 if (!JsonToken.START_OBJECT.equals(token))
156 fail(parser, "The root-element must be an object!");
158 return new Spliterator<Entry<String, Object>>()
161 public boolean tryAdvance(Consumer<? super Entry<String, Object>> action)
165 JsonToken token = parser.nextToken();
167 fail(parser, "Unexpected end of data!");
168 if (JsonToken.END_OBJECT.equals(token))
170 if (parser.nextToken() != null)
171 fail(parser, "unexpected data after parsed object");
174 if (!JsonToken.FIELD_NAME.equals(token))
175 fail(parser, "expected a field-name");
176 final String key = parser.getText();
178 final Object value = convertInternal(parser);
179 action.accept(new Entry<String, Object>()
182 public String getKey()
188 public Object getValue()
194 public Object setValue(Object value)
196 throw new UnsupportedOperationException("Not supported.");
201 catch (IOException e)
203 throw new IllegalArgumentException(e);
208 public Spliterator<Entry<String, Object>> trySplit()
214 public long estimateSize()
216 return Long.MAX_VALUE;
220 public int characteristics()
227 public static Stream<Entry<String, Object>> getObjectStream(final JsonParser parser)
231 return StreamSupport.stream(getObjectSpliterator(parser), false);
234 public static Iterator<Entry<String, Object>> getObjectIterator(
235 final JsonParser parser
240 Spliterator<Entry<String, Object>> spliterator = getObjectSpliterator(parser);
241 return new Iterator<Entry<String, Object>>()
243 private Entry<String, Object> next = null;
247 public boolean hasNext()
252 return spliterator.tryAdvance(new Consumer<Entry<String, Object>>()
255 public void accept(Entry<String, Object> e)
263 public Entry<String, Object> next()
265 if (next == null && !hasNext())
266 throw new NoSuchElementException();
267 Entry<String, Object> e = next;
275 public static List<Object> convertArray(JsonParser parser) throws IOException
277 JsonToken token = parser.nextToken();
281 LOG.warn("empty input");
282 return Collections.EMPTY_LIST;
285 if (!JsonToken.START_ARRAY.equals(token))
286 fail(parser, "The root-element must be an array!");
288 List<Object> array = convertArrayInternal(parser);
290 if (parser.nextToken() != null)
291 fail(parser, "unexpected data after parsed array");
296 public static Map<String, Object> convertObject(JsonParser parser) throws IOException
298 JsonToken token = parser.nextToken();
302 LOG.warn("empty input");
303 return Collections.EMPTY_MAP;
306 if (!JsonToken.START_OBJECT.equals(token))
307 fail(parser, "The root-element must be an object!");
309 Map<String, Object> object = convertObjectInternal(parser);
311 if (parser.nextToken() != null)
312 fail(parser, "unexpected data after parsed object");
317 public static Object convert(JsonParser parser) throws IOException
319 JsonToken token = parser.nextToken();
323 LOG.warn("empty input");
333 fail(parser, "The root-element must be either an object or an array!");
336 Object object = convertInternal(parser);
338 if (parser.nextToken() != null)
339 fail(parser, "unexpected data after parsed object");
345 static Object convertInternal(JsonParser parser) throws IOException
347 JsonToken token = parser.getCurrentToken();
349 fail(parser, "unexpected EOF");
353 case VALUE_STRING: return parser.getText();
354 case VALUE_NUMBER_INT: return parser.getIntValue();
355 case VALUE_NUMBER_FLOAT: return parser.getDoubleValue();
356 case START_OBJECT: return convertObjectInternal(parser);
357 case START_ARRAY: return convertArrayInternal(parser);
358 case VALUE_TRUE: return Boolean.TRUE;
359 case VALUE_FALSE: return Boolean.FALSE;
360 case VALUE_NULL: return null;
363 fail(parser, "unexpected token " + token.toString());
364 return null; // << Will never be reached, because fail always throws an exception
368 static Map<String, Object> convertObjectInternal(JsonParser parser)
372 JsonToken token = parser.nextToken();
374 fail(parser, "unexpected EOF");
376 Map<String, Object> map = new LinkedHashMap<>();
378 while (!JsonToken.END_OBJECT.equals(token))
380 if (!JsonToken.FIELD_NAME.equals(token))
381 fail(parser, "expected a field-name");
383 String name = parser.getText();
385 Object value = convertInternal(parser);
386 map.put(name, value);
388 token = parser.nextToken();
390 fail(parser, "unexpected EOF");
396 static List<Object> convertArrayInternal(JsonParser parser) throws IOException
398 JsonToken token = parser.nextToken();
400 fail(parser, "unexpected EOF");
402 List<Object> list = new LinkedList<>();
404 while (!JsonToken.END_ARRAY.equals(token))
406 list.add(convertInternal(parser));
408 token = parser.nextToken();
410 fail(parser, "unexpected EOF");
417 static void fail(JsonParser parser, String message)
419 JsonLocation location = parser.getCurrentLocation();
421 "{} at char-offset {} (line {}, column {})",
423 location.getCharOffset(),
424 location.getLineNr(),
425 location.getColumnNr()
427 throw new IllegalArgumentException("Cannot parse JSON: " + message);