-package de.juplo.jackson;
-
-
-import com.fasterxml.jackson.core.JsonLocation;
-import com.fasterxml.jackson.core.JsonParser;
-import com.fasterxml.jackson.core.JsonToken;
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.NoSuchElementException;
-import java.util.Spliterator;
-import static java.util.Spliterator.IMMUTABLE;
-import java.util.function.Consumer;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-
-
-/**
- *
- * @author kai
- */
-public abstract class SimpleMapper
-{
- private static final Logger LOG =
- LoggerFactory.getLogger(SimpleMapper.class);
-
-
- public static Spliterator<Object> getArraySpliterator(final JsonParser parser)
- throws
- IOException
- {
- JsonToken token = parser.nextToken();
-
- if (token == null)
- return null;
-
- if (!JsonToken.START_ARRAY.equals(token))
- fail(parser, "The root-element must be an array!");
-
- return new Spliterator<Object>()
- {
- @Override
- public boolean tryAdvance(Consumer<? super Object> action)
- {
- try
- {
- JsonToken token = parser.nextToken();
- if (token == null)
- fail(parser, "Unexpected end of data!");
- if (JsonToken.END_ARRAY.equals(token))
- {
- if (parser.nextToken() != null)
- fail(parser, "unexpected data after parsed array");
- return false;
- }
- action.accept(convertInternal(parser));
- return true;
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException(e);
- }
- }
-
- @Override
- public Spliterator<Object> trySplit()
- {
- return null;
- }
-
- @Override
- public long estimateSize()
- {
- return Long.MAX_VALUE;
- }
-
- @Override
- public int characteristics()
- {
- return IMMUTABLE;
- }
- };
- }
-
- public static Stream<Object> getArrayStream(final JsonParser parser)
- throws
- IOException
- {
- return StreamSupport.stream(getArraySpliterator(parser), false);
- }
-
- public static Iterator<Object> getArrayIterator(final JsonParser parser)
- throws
- IOException
- {
- Spliterator<Object> spliterator = getArraySpliterator(parser);
- return new Iterator<Object>()
- {
- private Object next = null;
-
-
- @Override
- public boolean hasNext()
- {
- if (next != null)
- return true;
-
- return spliterator.tryAdvance((Object o) -> { next = o; });
- }
-
- @Override
- public Object next()
- {
- if (next == null && !hasNext())
- throw new NoSuchElementException();
- Object o = next;
- next = null;
- return o;
- }
- };
- }
-
-
- public static Spliterator<Entry<String, Object>> getObjectSpliterator(final JsonParser parser)
- throws
- IOException
- {
- JsonToken token = parser.nextToken();
-
- if (token == null)
- return null;
-
- if (!JsonToken.START_OBJECT.equals(token))
- fail(parser, "The root-element must be an object!");
-
- return new Spliterator<Entry<String, Object>>()
- {
- @Override
- public boolean tryAdvance(Consumer<? super Entry<String, Object>> action)
- {
- try
- {
- JsonToken token = parser.nextToken();
- if (token == null)
- fail(parser, "Unexpected end of data!");
- if (JsonToken.END_OBJECT.equals(token))
- {
- if (parser.nextToken() != null)
- fail(parser, "unexpected data after parsed object");
- return false;
- }
- if (!JsonToken.FIELD_NAME.equals(token))
- fail(parser, "expected a field-name");
- final String key = parser.getText();
- parser.nextToken();
- final Object value = convertInternal(parser);
- action.accept(new Entry<String, Object>()
- {
- @Override
- public String getKey()
- {
- return key;
- }
-
- @Override
- public Object getValue()
- {
- return value;
- }
-
- @Override
- public Object setValue(Object value)
- {
- throw new UnsupportedOperationException("Not supported.");
- }
- });
- return true;
- }
- catch (IOException e)
- {
- throw new IllegalArgumentException(e);
- }
- }
-
- @Override
- public Spliterator<Entry<String, Object>> trySplit()
- {
- return null;
- }
-
- @Override
- public long estimateSize()
- {
- return Long.MAX_VALUE;
- }
-
- @Override
- public int characteristics()
- {
- return IMMUTABLE;
- }
- };
- }
-
- public static Stream<Entry<String, Object>> getObjectStream(final JsonParser parser)
- throws
- IOException
- {
- return StreamSupport.stream(getObjectSpliterator(parser), false);
- }
-
- public static Iterator<Entry<String, Object>> getObjectIterator(
- final JsonParser parser
- )
- throws
- IOException
- {
- Spliterator<Entry<String, Object>> spliterator = getObjectSpliterator(parser);
- return new Iterator<Entry<String, Object>>()
- {
- private Entry<String, Object> next = null;
-
-
- @Override
- public boolean hasNext()
- {
- if (next != null)
- return true;
-
- return spliterator.tryAdvance((Entry<String, Object> e) -> { next = e; });
- }
-
- @Override
- public Entry<String, Object> next()
- {
- if (next == null && !hasNext())
- throw new NoSuchElementException();
- Entry<String, Object> e = next;
- next = null;
- return e;
- }
- };
- }
-
-
- public static List<Object> convertArray(JsonParser parser) throws IOException
- {
- JsonToken token = parser.nextToken();
-
- if (token == null)
- return null;
-
- if (!JsonToken.START_ARRAY.equals(token))
- fail(parser, "The root-element must be an array!");
-
- List<Object> array = convertArrayInternal(parser);
-
- if (parser.nextToken() != null)
- fail(parser, "unexpected data after parsed array");
-
- return array;
- }
-
- public static Map<String, Object> convertObject(JsonParser parser) throws IOException
- {
- JsonToken token = parser.nextToken();
-
- if (token == null)
- return null;
-
- if (!JsonToken.START_OBJECT.equals(token))
- fail(parser, "The root-element must be an object!");
-
- Map<String, Object> object = convertObjectInternal(parser);
-
- if (parser.nextToken() != null)
- fail(parser, "unexpected data after parsed object");
-
- return object;
- }
-
- public static Object convert(JsonParser parser) throws IOException
- {
- JsonToken token = parser.nextToken();
-
- if (token == null)
- return null;
-
- switch (token)
- {
- case START_ARRAY:
- case START_OBJECT:
- break;
- default:
- fail(parser, "The root-element must be either an object or an array!");
- }
-
- Object object = convertInternal(parser);
-
- if (parser.nextToken() != null)
- fail(parser, "unexpected data after parsed object");
-
- return object;
- }
-
-
- static Object convertInternal(JsonParser parser) throws IOException
- {
- JsonToken token = parser.getCurrentToken();
- if (token == null)
- {
- fail(parser, "unexpected EOF");
- return null; // << Will never be reached, because fail always throws an exception
- }
-
- switch (token)
- {
- case VALUE_STRING: return parser.getText();
- case VALUE_NUMBER_INT: return parser.getIntValue();
- case VALUE_NUMBER_FLOAT: return parser.getDoubleValue();
- case START_OBJECT: return convertObjectInternal(parser);
- case START_ARRAY: return convertArrayInternal(parser);
- case VALUE_TRUE: return Boolean.TRUE;
- case VALUE_FALSE: return Boolean.FALSE;
- case VALUE_NULL: return null;
- }
-
- fail(parser, "unexpected token " + token);
- return null; // << Will never be reached, because fail always throws an exception
- }
-
-
- static Map<String, Object> convertObjectInternal(JsonParser parser)
- throws
- IOException
- {
- JsonToken token = parser.nextToken();
- if (token == null)
- fail(parser, "unexpected EOF");
-
- Map<String, Object> map = new LinkedHashMap<>();
-
- while (!JsonToken.END_OBJECT.equals(token))
- {
- if (!JsonToken.FIELD_NAME.equals(token))
- fail(parser, "expected a field-name");
-
- String name = parser.getText();
- parser.nextToken();
- Object value = convertInternal(parser);
- map.put(name, value);
-
- token = parser.nextToken();
- if (token == null)
- fail(parser, "unexpected EOF");
- }
-
- return map;
- }
-
- static List<Object> convertArrayInternal(JsonParser parser) throws IOException
- {
- JsonToken token = parser.nextToken();
- if (token == null)
- fail(parser, "unexpected EOF");
-
- List<Object> list = new LinkedList<>();
-
- while (!JsonToken.END_ARRAY.equals(token))
- {
- list.add(convertInternal(parser));
-
- token = parser.nextToken();
- if (token == null)
- fail(parser, "unexpected EOF");
- }
-
- return list;
- }
-
-
- static void fail(JsonParser parser, String message)
- {
- JsonLocation location = parser.getCurrentLocation();
- LOG.error(
- "{} at char-offset {} (line {}, column {})",
- message,
- location.getCharOffset(),
- location.getLineNr(),
- location.getColumnNr()
- );
- throw new IllegalArgumentException("Cannot parse JSON: " + message);
- }
-}