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((Object o) -> { next = o; });
126 if (next == null && !hasNext())
127 throw new NoSuchElementException();
136 public static Spliterator<Entry<String, Object>> getObjectSpliterator(final JsonParser parser)
140 JsonToken token = parser.nextToken();
144 LOG.warn("empty input");
145 return Spliterators.emptySpliterator();
148 if (!JsonToken.START_OBJECT.equals(token))
149 fail(parser, "The root-element must be an object!");
151 return new Spliterator<Entry<String, Object>>()
154 public boolean tryAdvance(Consumer<? super Entry<String, Object>> action)
158 JsonToken token = parser.nextToken();
160 fail(parser, "Unexpected end of data!");
161 if (JsonToken.END_OBJECT.equals(token))
163 if (parser.nextToken() != null)
164 fail(parser, "unexpected data after parsed object");
167 if (!JsonToken.FIELD_NAME.equals(token))
168 fail(parser, "expected a field-name");
169 final String key = parser.getText();
171 final Object value = convertInternal(parser);
172 action.accept(new Entry<String, Object>()
175 public String getKey()
181 public Object getValue()
187 public Object setValue(Object value)
189 throw new UnsupportedOperationException("Not supported.");
194 catch (IOException e)
196 throw new IllegalArgumentException(e);
201 public Spliterator<Entry<String, Object>> trySplit()
207 public long estimateSize()
209 return Long.MAX_VALUE;
213 public int characteristics()
220 public static Stream<Entry<String, Object>> getObjectStream(final JsonParser parser)
224 return StreamSupport.stream(getObjectSpliterator(parser), false);
227 public static Iterator<Entry<String, Object>> getObjectIterator(
228 final JsonParser parser
233 Spliterator<Entry<String, Object>> spliterator = getObjectSpliterator(parser);
234 return new Iterator<Entry<String, Object>>()
236 private Entry<String, Object> next = null;
240 public boolean hasNext()
245 return spliterator.tryAdvance((Entry<String, Object> e) -> { next = e; });
249 public Entry<String, Object> next()
251 if (next == null && !hasNext())
252 throw new NoSuchElementException();
253 Entry<String, Object> e = next;
261 public static List<Object> convertArray(JsonParser parser) throws IOException
263 JsonToken token = parser.nextToken();
267 LOG.warn("empty input");
268 return Collections.EMPTY_LIST;
271 if (!JsonToken.START_ARRAY.equals(token))
272 fail(parser, "The root-element must be an array!");
274 List<Object> array = convertArrayInternal(parser);
276 if (parser.nextToken() != null)
277 fail(parser, "unexpected data after parsed array");
282 public static Map<String, Object> convertObject(JsonParser parser) throws IOException
284 JsonToken token = parser.nextToken();
288 LOG.warn("empty input");
289 return Collections.EMPTY_MAP;
292 if (!JsonToken.START_OBJECT.equals(token))
293 fail(parser, "The root-element must be an object!");
295 Map<String, Object> object = convertObjectInternal(parser);
297 if (parser.nextToken() != null)
298 fail(parser, "unexpected data after parsed object");
303 public static Object convert(JsonParser parser) throws IOException
305 JsonToken token = parser.nextToken();
309 LOG.warn("empty input");
319 fail(parser, "The root-element must be either an object or an array!");
322 Object object = convertInternal(parser);
324 if (parser.nextToken() != null)
325 fail(parser, "unexpected data after parsed object");
331 static Object convertInternal(JsonParser parser) throws IOException
333 JsonToken token = parser.getCurrentToken();
335 fail(parser, "unexpected EOF");
339 case VALUE_STRING: return parser.getText();
340 case VALUE_NUMBER_INT: return parser.getIntValue();
341 case VALUE_NUMBER_FLOAT: return parser.getDoubleValue();
342 case START_OBJECT: return convertObjectInternal(parser);
343 case START_ARRAY: return convertArrayInternal(parser);
344 case VALUE_TRUE: return Boolean.TRUE;
345 case VALUE_FALSE: return Boolean.FALSE;
346 case VALUE_NULL: return null;
349 fail(parser, "unexpected token " + token.toString());
350 return null; // << Will never be reached, because fail always throws an exception
354 static Map<String, Object> convertObjectInternal(JsonParser parser)
358 JsonToken token = parser.nextToken();
360 fail(parser, "unexpected EOF");
362 Map<String, Object> map = new LinkedHashMap<>();
364 while (!JsonToken.END_OBJECT.equals(token))
366 if (!JsonToken.FIELD_NAME.equals(token))
367 fail(parser, "expected a field-name");
369 String name = parser.getText();
371 Object value = convertInternal(parser);
372 map.put(name, value);
374 token = parser.nextToken();
376 fail(parser, "unexpected EOF");
382 static List<Object> convertArrayInternal(JsonParser parser) throws IOException
384 JsonToken token = parser.nextToken();
386 fail(parser, "unexpected EOF");
388 List<Object> list = new LinkedList<>();
390 while (!JsonToken.END_ARRAY.equals(token))
392 list.add(convertInternal(parser));
394 token = parser.nextToken();
396 fail(parser, "unexpected EOF");
403 static void fail(JsonParser parser, String message)
405 JsonLocation location = parser.getCurrentLocation();
407 "{} at char-offset {} (line {}, column {})",
409 location.getCharOffset(),
410 location.getLineNr(),
411 location.getColumnNr()
413 throw new IllegalArgumentException("Cannot parse JSON: " + message);