1 package de.juplo.jackson;
4 import com.fasterxml.jackson.core.JsonFactory;
5 import com.fasterxml.jackson.core.JsonLocation;
6 import com.fasterxml.jackson.core.JsonParser;
7 import com.fasterxml.jackson.core.JsonToken;
8 import java.io.IOException;
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 class SimpleMapper
33 private static final Logger LOG =
34 LoggerFactory.getLogger(SimpleMapper.class);
37 private JsonFactory factory = new JsonFactory();
40 public static Stream<Object> getArrayStream(final JsonParser parser)
44 return StreamSupport.stream(getArraySpliterator(parser), false);
47 public static Spliterator<Object> getArraySpliterator(final JsonParser parser)
51 JsonToken token = parser.nextToken();
55 LOG.warn("empty input");
56 return Spliterators.emptySpliterator();
59 if (!JsonToken.START_ARRAY.equals(token))
60 fail(parser, "The root-element must be an array!");
62 return new Spliterator<Object>()
65 public boolean tryAdvance(Consumer<? super Object> action)
69 JsonToken token = parser.nextToken();
71 fail(parser, "Unexpected end of data!");
72 if (JsonToken.END_ARRAY.equals(token))
74 action.accept(convert(parser));
79 throw new IllegalArgumentException(e);
84 public Spliterator<Object> trySplit()
90 public long estimateSize()
92 return Long.MAX_VALUE;
96 public int characteristics()
103 public static Iterator<Object> getArrayIterator(final JsonParser parser)
107 Spliterator<Object> spliterator = getArraySpliterator(parser);
108 return new Iterator<Object>()
110 private Object next = null;
114 public boolean hasNext()
119 return spliterator.tryAdvance(new Consumer<Object>()
122 public void accept(Object o)
132 if (next == null && !hasNext())
133 throw new NoSuchElementException();
142 public static Stream<Entry<String, Object>> getObjectStream(final JsonParser parser)
146 return StreamSupport.stream(getObjectSpliterator(parser), false);
149 public static Spliterator<Entry<String, Object>> getObjectSpliterator(final JsonParser parser)
153 JsonToken token = parser.nextToken();
157 LOG.warn("empty input");
158 return Spliterators.emptySpliterator();
161 if (!JsonToken.START_OBJECT.equals(token))
162 fail(parser, "The root-element must be an array!");
164 return new Spliterator<Entry<String, Object>>()
167 public boolean tryAdvance(Consumer<? super Entry<String, Object>> action)
171 JsonToken token = parser.nextToken();
173 fail(parser, "Unexpected end of data!");
174 if (JsonToken.END_OBJECT.equals(token))
176 if (!JsonToken.FIELD_NAME.equals(token))
177 fail(parser, "expected a field-name");
178 final String key = parser.getText();
180 final Object value = convert(parser);
181 action.accept(new Entry<String, Object>()
184 public String getKey()
190 public Object getValue()
196 public Object setValue(Object value)
198 throw new UnsupportedOperationException("Not supported.");
203 catch (IOException e)
205 throw new IllegalArgumentException(e);
210 public Spliterator<Entry<String, Object>> trySplit()
216 public long estimateSize()
218 return Long.MAX_VALUE;
222 public int characteristics()
229 public static Iterator<Entry<String, Object>> getObjectIterator(
230 final JsonParser parser
235 Spliterator<Entry<String, Object>> spliterator = getObjectSpliterator(parser);
236 return new Iterator<Entry<String, Object>>()
238 private Entry<String, Object> next = null;
242 public boolean hasNext()
247 return spliterator.tryAdvance(new Consumer<Entry<String, Object>>()
250 public void accept(Entry<String, Object> e)
258 public Entry<String, Object> next()
260 if (next == null && !hasNext())
261 throw new NoSuchElementException();
262 Entry<String, Object> e = next;
270 static Object convert(JsonParser parser) throws IOException
272 JsonToken token = parser.getCurrentToken();
274 fail(parser, "unexpected EOF");
278 case VALUE_STRING: return parser.getText();
279 case VALUE_NUMBER_INT: return parser.getIntValue();
280 case VALUE_NUMBER_FLOAT: return parser.getDoubleValue();
281 case START_OBJECT: return convertObject(parser);
282 case START_ARRAY: return convertArray(parser);
283 case VALUE_TRUE: return Boolean.TRUE;
284 case VALUE_FALSE: return Boolean.FALSE;
285 case VALUE_NULL: return null;
288 fail(parser, "unexpected token " + token.toString());
289 return null; // << Will never be reached, because fail always throws an exception
292 static Map<String, Object> convertObject(JsonParser parser) throws IOException
294 JsonToken token = parser.nextToken();
296 fail(parser, "unexpected EOF");
298 Map<String, Object> map = new LinkedHashMap<>();
300 while (!JsonToken.END_OBJECT.equals(token))
302 if (!JsonToken.FIELD_NAME.equals(token))
303 fail(parser, "expected a field-name");
305 String name = parser.getText();
307 Object value = convert(parser);
308 map.put(name, value);
310 token = parser.nextToken();
312 fail(parser, "unexpected EOF");
318 static List<Object> convertArray(JsonParser parser) throws IOException
320 JsonToken token = parser.nextToken();
322 fail(parser, "unexpected EOF");
324 List<Object> list = new LinkedList<>();
326 while (!JsonToken.END_ARRAY.equals(token))
328 list.add(convert(parser));
330 token = parser.nextToken();
332 fail(parser, "unexpected EOF");
338 static void fail(JsonParser parser, String message)
340 JsonLocation location = parser.getCurrentLocation();
342 "{} at char-offset {} (line {}, column {})",
344 location.getCharOffset(),
345 location.getLineNr(),
346 location.getColumnNr()
348 throw new IllegalArgumentException("Cannot parse JSON: " + message);