Initial implementation of SimpleMapper
authorKai Moritz <kai@juplo.de>
Mon, 13 Jun 2016 12:52:51 +0000 (14:52 +0200)
committerKai Moritz <kai@juplo.de>
Wed, 22 Jun 2016 08:32:57 +0000 (10:32 +0200)
.gitignore [new file with mode: 0644]
pom.xml [new file with mode: 0644]
src/main/java/de/juplo/jackson/SimpleMapper.java [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..a6f89c2
--- /dev/null
@@ -0,0 +1 @@
+/target/
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644 (file)
index 0000000..ec1fc3a
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,69 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>de.juplo.jackson</groupId>
+  <artifactId>simple-mapper</artifactId>
+  <version>1.0-SNAPSHOT</version>
+
+  <properties>
+
+    <!-- settings for Spring-Boot -->
+    <java.version>1.8</java.version>
+
+    <!-- other usefull settings -->
+    <encoding>UTF-8</encoding>
+    <maven.compiler.source>1.8</maven.compiler.source>
+    <maven.compiler.target>1.8</maven.compiler.target>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+
+  </properties>
+
+  <dependencies>
+
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-annotations</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-databind</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+
+
+    <!-- Testing -->
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+  </dependencies>
+
+  <dependencyManagement>
+     <dependencies>
+      <dependency>
+        <!-- Import dependency management from Spring Boot -->
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-dependencies</artifactId>
+        <version>1.3.5.RELEASE</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
+</project>
diff --git a/src/main/java/de/juplo/jackson/SimpleMapper.java b/src/main/java/de/juplo/jackson/SimpleMapper.java
new file mode 100644 (file)
index 0000000..0426720
--- /dev/null
@@ -0,0 +1,971 @@
+package de.juplo.jackson;
+
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonLocation;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.net.URL;
+import java.util.Collections;
+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.Spliterators;
+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 class SimpleMapper
+{
+  private static final Logger LOG =
+      LoggerFactory.getLogger(SimpleMapper.class);
+
+
+  private final JsonFactory factory;
+
+
+  public SimpleMapper(JsonFactory factory)
+  {
+    this.factory = factory;
+  }
+
+
+  public Spliterator<Object> getArraySpliterator(File file)
+      throws
+        IOException
+  {
+    return getArraySpliterator(factory.createParser(file));
+  }
+
+  public Spliterator<Object> getArraySpliterator(InputStream is)
+      throws
+        IOException
+  {
+    return getArraySpliterator(factory.createParser(is));
+  }
+
+  public Spliterator<Object> getArraySpliterator(Reader r)
+      throws
+        IOException
+  {
+    return getArraySpliterator(factory.createParser(r));
+  }
+
+  public Spliterator<Object> getArraySpliterator(String content)
+      throws
+        IOException
+  {
+    return getArraySpliterator(factory.createParser(content));
+  }
+
+  public Spliterator<Object> getArraySpliterator(URL url)
+      throws
+        IOException
+  {
+    return getArraySpliterator(factory.createParser(url));
+  }
+
+  public Spliterator<Object> getArraySpliterator(byte[] data)
+      throws
+        IOException
+  {
+    return getArraySpliterator(factory.createParser(data));
+  }
+
+  public Spliterator<Object> getArraySpliterator(char[] content)
+      throws
+        IOException
+  {
+    return getArraySpliterator(factory.createParser(content));
+  }
+
+  public Spliterator<Object> getArraySpliterator(byte[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getArraySpliterator(factory.createParser(data, offset, len));
+  }
+
+  public Spliterator<Object> getArraySpliterator(char[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getArraySpliterator(factory.createParser(data, offset, len));
+  }
+
+  public Stream<Object> getArrayStream(File file)
+      throws
+        IOException
+  {
+    return getArrayStream(factory.createParser(file));
+  }
+
+  public Stream<Object> getArrayStream(InputStream is)
+      throws
+        IOException
+  {
+    return getArrayStream(factory.createParser(is));
+  }
+
+  public Stream<Object> getArrayStream(Reader r)
+      throws
+        IOException
+  {
+    return getArrayStream(factory.createParser(r));
+  }
+
+  public Stream<Object> getArrayStream(String content)
+      throws
+        IOException
+  {
+    return getArrayStream(factory.createParser(content));
+  }
+
+  public Stream<Object> getArrayStream(URL url)
+      throws
+        IOException
+  {
+    return getArrayStream(factory.createParser(url));
+  }
+
+  public Stream<Object> getArrayStream(byte[] data)
+      throws
+        IOException
+  {
+    return getArrayStream(factory.createParser(data));
+  }
+
+  public Stream<Object> getArrayStream(char[] content)
+      throws
+        IOException
+  {
+    return getArrayStream(factory.createParser(content));
+  }
+
+  public Stream<Object> getArrayStream(byte[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getArrayStream(factory.createParser(data, offset, len));
+  }
+
+  public Stream<Object> getArrayStream(char[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getArrayStream(factory.createParser(data, offset, len));
+  }
+
+  public Iterator<Object> getArrayIterator(File file)
+      throws
+        IOException
+  {
+    return getArrayIterator(factory.createParser(file));
+  }
+
+  public Iterator<Object> getArrayIterator(InputStream is)
+      throws
+        IOException
+  {
+    return getArrayIterator(factory.createParser(is));
+  }
+
+  public Iterator<Object> getArrayIterator(Reader r)
+      throws
+        IOException
+  {
+    return getArrayIterator(factory.createParser(r));
+  }
+
+  public Iterator<Object> getArrayIterator(String content)
+      throws
+        IOException
+  {
+    return getArrayIterator(factory.createParser(content));
+  }
+
+  public Iterator<Object> getArrayIterator(URL url)
+      throws
+        IOException
+  {
+    return getArrayIterator(factory.createParser(url));
+  }
+
+  public Iterator<Object> getArrayIterator(byte[] data)
+      throws
+        IOException
+  {
+    return getArrayIterator(factory.createParser(data));
+  }
+
+  public Iterator<Object> getArrayIterator(char[] content)
+      throws
+        IOException
+  {
+    return getArrayIterator(factory.createParser(content));
+  }
+
+  public Iterator<Object> getArrayIterator(byte[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getArrayIterator(factory.createParser(data, offset, len));
+  }
+
+  public Iterator<Object> getArrayIterator(char[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getArrayIterator(factory.createParser(data, offset, len));
+  }
+
+
+  public Spliterator<Entry<String, Object>> getObjectSpliterator(File file)
+      throws
+        IOException
+  {
+    return getObjectSpliterator(factory.createParser(file));
+  }
+
+  public Spliterator<Entry<String, Object>> getObjectSpliterator(InputStream is)
+      throws
+        IOException
+  {
+    return getObjectSpliterator(factory.createParser(is));
+  }
+
+  public Spliterator<Entry<String, Object>> getObjectSpliterator(Reader r)
+      throws
+        IOException
+  {
+    return getObjectSpliterator(factory.createParser(r));
+  }
+
+  public Spliterator<Entry<String, Object>> getObjectSpliterator(String content)
+      throws
+        IOException
+  {
+    return getObjectSpliterator(factory.createParser(content));
+  }
+
+  public Spliterator<Entry<String, Object>> getObjectSpliterator(URL url)
+      throws
+        IOException
+  {
+    return getObjectSpliterator(factory.createParser(url));
+  }
+
+  public Spliterator<Entry<String, Object>> getObjectSpliterator(byte[] data)
+      throws
+        IOException
+  {
+    return getObjectSpliterator(factory.createParser(data));
+  }
+
+  public Spliterator<Entry<String, Object>> getObjectSpliterator(char[] content)
+      throws
+        IOException
+  {
+    return getObjectSpliterator(factory.createParser(content));
+  }
+
+  public Spliterator<Entry<String, Object>> getObjectSpliterator(byte[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getObjectSpliterator(factory.createParser(data, offset, len));
+  }
+
+  public Spliterator<Entry<String, Object>> getObjectSpliterator(char[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getObjectSpliterator(factory.createParser(data, offset, len));
+  }
+
+  public Stream<Entry<String, Object>> getObjectStream(File file)
+      throws
+        IOException
+  {
+    return getObjectStream(factory.createParser(file));
+  }
+
+  public Stream<Entry<String, Object>> getObjectStream(InputStream is)
+      throws
+        IOException
+  {
+    return getObjectStream(factory.createParser(is));
+  }
+
+  public Stream<Entry<String, Object>> getObjectStream(Reader r)
+      throws
+        IOException
+  {
+    return getObjectStream(factory.createParser(r));
+  }
+
+  public Stream<Entry<String, Object>> getObjectStream(String content)
+      throws
+        IOException
+  {
+    return getObjectStream(factory.createParser(content));
+  }
+
+  public Stream<Entry<String, Object>> getObjectStream(URL url)
+      throws
+        IOException
+  {
+    return getObjectStream(factory.createParser(url));
+  }
+
+  public Stream<Entry<String, Object>> getObjectStream(byte[] data)
+      throws
+        IOException
+  {
+    return getObjectStream(factory.createParser(data));
+  }
+
+  public Stream<Entry<String, Object>> getObjectStream(char[] content)
+      throws
+        IOException
+  {
+    return getObjectStream(factory.createParser(content));
+  }
+
+  public Stream<Entry<String, Object>> getObjectStream(byte[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getObjectStream(factory.createParser(data, offset, len));
+  }
+
+  public Stream<Entry<String, Object>> getObjectStream(char[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getObjectStream(factory.createParser(data, offset, len));
+  }
+
+  public Iterator<Entry<String, Object>> getObjectIterator(File file)
+      throws
+        IOException
+  {
+    return getObjectIterator(factory.createParser(file));
+  }
+
+  public Iterator<Entry<String, Object>> getObjectIterator(InputStream is)
+      throws
+        IOException
+  {
+    return getObjectIterator(factory.createParser(is));
+  }
+
+  public Iterator<Entry<String, Object>> getObjectIterator(Reader r)
+      throws
+        IOException
+  {
+    return getObjectIterator(factory.createParser(r));
+  }
+
+  public Iterator<Entry<String, Object>> getObjectIterator(String content)
+      throws
+        IOException
+  {
+    return getObjectIterator(factory.createParser(content));
+  }
+
+  public Iterator<Entry<String, Object>> getObjectIterator(URL url)
+      throws
+        IOException
+  {
+    return getObjectIterator(factory.createParser(url));
+  }
+
+  public Iterator<Entry<String, Object>> getObjectIterator(byte[] data)
+      throws
+        IOException
+  {
+    return getObjectIterator(factory.createParser(data));
+  }
+
+  public Iterator<Entry<String, Object>> getObjectIterator(char[] content)
+      throws
+        IOException
+  {
+    return getObjectIterator(factory.createParser(content));
+  }
+
+  public Iterator<Entry<String, Object>> getObjectIterator(byte[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getObjectIterator(factory.createParser(data, offset, len));
+  }
+
+  public Iterator<Entry<String, Object>> getObjectIterator(char[] data, int offset, int len)
+      throws
+        IOException
+  {
+    return getObjectIterator(factory.createParser(data, offset, len));
+  }
+
+
+  public static Spliterator<Object> getArraySpliterator(final JsonParser parser)
+      throws
+        IOException
+  {
+    JsonToken token = parser.nextToken();
+
+    if (token == null)
+    {
+      LOG.warn("empty input");
+      return Spliterators.emptySpliterator();
+    }
+
+    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(new Consumer<Object>()
+        {
+          @Override
+          public void accept(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)
+    {
+      LOG.warn("empty input");
+      return Spliterators.emptySpliterator();
+    }
+
+    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(new Consumer<Entry<String, Object>>()
+        {
+          @Override
+          public void accept(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 List<Object> convertArray(File file) throws Exception
+  {
+    return convertArray(factory.createParser(file));
+  }
+
+  public List<Object> convertArray(InputStream is) throws Exception
+  {
+    return convertArray(factory.createParser(is));
+  }
+
+  public List<Object> convertArray(Reader r) throws Exception
+  {
+    return convertArray(factory.createParser(r));
+  }
+
+  public List<Object> convertArray(String content) throws Exception
+  {
+    return convertArray(factory.createParser(content));
+  }
+
+  public List<Object> convertArray(URL url) throws Exception
+  {
+    return convertArray(factory.createParser(url));
+  }
+
+  public List<Object> convertArray(byte[] data) throws Exception
+  {
+    return convertArray(factory.createParser(data));
+  }
+
+  public List<Object> convertArray(char[] content) throws Exception
+  {
+    return convertArray(factory.createParser(content));
+  }
+
+  public List<Object> convertArray(byte[] data, int offset, int len)
+      throws
+        Exception
+  {
+    return convertArray(factory.createParser(data, offset, len));
+  }
+
+  public List<Object> convertArray(char[] content, int offset, int len)
+      throws
+        Exception
+  {
+    return convertArray(factory.createParser(content, offset, len));
+  }
+
+  public Map<String, Object> convertObject(File file) throws Exception
+  {
+    return convertObject(factory.createParser(file));
+  }
+
+  public Map<String, Object> convertObject(InputStream is) throws Exception
+  {
+    return convertObject(factory.createParser(is));
+  }
+
+  public Map<String, Object> convertObject(Reader r) throws Exception
+  {
+    return convertObject(factory.createParser(r));
+  }
+
+  public Map<String, Object> convertObject(String content) throws Exception
+  {
+    return convertObject(factory.createParser(content));
+  }
+
+  public Map<String, Object> convertObject(URL url) throws Exception
+  {
+    return convertObject(factory.createParser(url));
+  }
+
+  public Map<String, Object> convertObject(byte[] data) throws Exception
+  {
+    return convertObject(factory.createParser(data));
+  }
+
+  public Map<String, Object> convertObject(char[] content) throws Exception
+  {
+    return convertObject(factory.createParser(content));
+  }
+
+  public Map<String, Object> convertObject(byte[] data, int offset, int len)
+      throws
+        Exception
+  {
+    return convertObject(factory.createParser(data, offset, len));
+  }
+
+  public Map<String, Object> convertObject(char[] content, int offset, int len)
+      throws
+        Exception
+  {
+    return convertObject(factory.createParser(content, offset, len));
+  }
+
+  public Object convert(File file) throws Exception
+  {
+    return convert(factory.createParser(file));
+  }
+
+  public Object convert(InputStream is) throws Exception
+  {
+    return convert(factory.createParser(is));
+  }
+
+  public Object convert(Reader r) throws Exception
+  {
+    return convert(factory.createParser(r));
+  }
+
+  public Object convert(String content) throws Exception
+  {
+    return convert(factory.createParser(content));
+  }
+
+  public Object convert(URL url) throws Exception
+  {
+    return convert(factory.createParser(url));
+  }
+
+  public Object convert(byte[] data) throws Exception
+  {
+    return convert(factory.createParser(data));
+  }
+
+  public Object convert(char[] content) throws Exception
+  {
+    return convert(factory.createParser(content));
+  }
+
+  public Object convert(byte[] data, int offset, int len)
+      throws
+        Exception
+  {
+    return convert(factory.createParser(data, offset, len));
+  }
+
+  public Object convert(char[] content, int offset, int len)
+      throws
+        Exception
+  {
+    return convert(factory.createParser(content, offset, len));
+  }
+
+
+  static List<Object> convertArray(JsonParser parser) throws IOException
+  {
+    JsonToken token = parser.nextToken();
+
+    if (token == null)
+    {
+      LOG.warn("empty input");
+      return Collections.EMPTY_LIST;
+    }
+
+    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;
+  }
+
+  static Map<String, Object> convertObject(JsonParser parser) throws IOException
+  {
+    JsonToken token = parser.nextToken();
+
+    if (token == null)
+    {
+      LOG.warn("empty input");
+      return Collections.EMPTY_MAP;
+    }
+
+    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;
+  }
+
+  static Object convert(JsonParser parser) throws IOException
+  {
+    JsonToken token = parser.nextToken();
+
+    if (token == null)
+    {
+      LOG.warn("empty input");
+      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");
+
+    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.toString());
+    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);
+  }
+}