gt:         ObjectNode node = nodeFactory.objectNode();
context: package com.fasterxml.jackson.databind.deser.std;
  
  import java.io.IOException;
  
  import com.fasterxml.jackson.core.*;
  import com.fasterxml.jackson.databind.*;
  import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
  import com.fasterxml.jackson.databind.node.*;
  
  /**
   * Deserializer that can build instances of {@link JsonNode} from any
   * JSON content, using appropriate {@link JsonNode} type.
   */
  @SuppressWarnings("serial")
  public class JsonNodeDeserializer
      extends BaseNodeDeserializer<JsonNode>
  {
      /**
       * Singleton instance of generic deserializer for {@link JsonNode}.
       * Only used for types other than JSON Object and Array.
       */
      private final static JsonNodeDeserializer instance = new JsonNodeDeserializer();
  
      protected JsonNodeDeserializer() { super(JsonNode.class); }
  
      /**
       * Factory method for accessing deserializer for specific node type
       */
      public static JsonDeserializer<? extends JsonNode> getDeserializer(Class<?> nodeClass)
      {
          if (nodeClass == ObjectNode.class) {
              return ObjectDeserializer.getInstance();
          }
          if (nodeClass == ArrayNode.class) {
              return ArrayDeserializer.getInstance();
          }
          // For others, generic one works fine
          return instance;
      }
      
      /*
      /**********************************************************
      /* Actual deserializer implementations
      /**********************************************************
       */
  
      @Override
      public JsonNode getNullValue() {
          return NullNode.getInstance();
      }
  
      /**
       * Implementation that will produce types of any JSON nodes; not just one
       * deserializer is registered to handle (in case of more specialized handler).
       * Overridden by typed sub-classes for more thorough checking
       */
      @Override
      public JsonNode deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
      {
          switch (jp.getCurrentTokenId()) {
          case JsonTokenId.ID_START_OBJECT:
              return deserializeObject(jp, ctxt, ctxt.getNodeFactory());
          case JsonTokenId.ID_START_ARRAY:
              return deserializeArray(jp, ctxt, ctxt.getNodeFactory());
          default:
              return deserializeAny(jp, ctxt, ctxt.getNodeFactory());
          }
      }
  
      /*
      /**********************************************************
      /* Specific instances for more accurate types
      /**********************************************************
       */
  
      final static class ObjectDeserializer
          extends BaseNodeDeserializer<ObjectNode>
      {
          private static final long serialVersionUID = 1L;
  
          protected final static ObjectDeserializer _instance = new ObjectDeserializer();
  
          protected ObjectDeserializer() { super(ObjectNode.class); }
  
          public static ObjectDeserializer getInstance() { return _instance; }
          
          @Override
          public ObjectNode deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
          {
              if (jp.getCurrentToken() == JsonToken.START_OBJECT) {
                  jp.nextToken();
                  return deserializeObject(jp, ctxt, ctxt.getNodeFactory());
              }
              if (jp.getCurrentToken() == JsonToken.FIELD_NAME) {
                  return deserializeObject(jp, ctxt, ctxt.getNodeFactory());
              }
              throw ctxt.mappingException(ObjectNode.class);
           }
      }
          
      final static class ArrayDeserializer
          extends BaseNodeDeserializer<ArrayNode>
      {
          private static final long serialVersionUID = 1L;
  
          protected final static ArrayDeserializer _instance = new ArrayDeserializer();
  
          protected ArrayDeserializer() { super(ArrayNode.class); }
  
          public static ArrayDeserializer getInstance() { return _instance; }
          
          @Override
          public ArrayNode deserialize(JsonParser jp, DeserializationContext ctxt)
              throws IOException, JsonProcessingException
          {
              if (jp.isExpectedStartArrayToken()) {
                  return deserializeArray(jp, ctxt, ctxt.getNodeFactory());
              }
              throw ctxt.mappingException(ArrayNode.class);
          }
      }
  }
  
  /**
   * Base class for all actual {@link JsonNode} deserializer
   * implementations
   */
  @SuppressWarnings("serial")
  abstract class BaseNodeDeserializer<T extends JsonNode>
      extends StdDeserializer<T>
  {
      public BaseNodeDeserializer(Class<T> vc) {
          super(vc);
      }
  
      @Override
      public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt,
              TypeDeserializer typeDeserializer)
          throws IOException
      {
          /* Output can be as JSON Object, Array or scalar: no way to know
           * a priori. So:
           */
          return typeDeserializer.deserializeTypedFromAny(jp, ctxt);
      }
  
      /* 07-Nov-2014, tatu: When investigating [databind#604], realized that it makes
       *   sense to also mark this is cachable, since lookup not exactly free, and
       *   since it's not uncommon to "read anything"
       */
      @Override
      public boolean isCachable() { return true; }
  
      /*
      /**********************************************************
      /* Overridable methods
      /**********************************************************
       */
  
      protected void _reportProblem(JsonParser jp, String msg) throws JsonMappingException {
          throw new JsonMappingException(msg, jp.getTokenLocation());
      }
  
      /**
       * 
       * @deprecated Since 2.3, use the overloaded variant
       */
      @Deprecated
      protected void _handleDuplicateField(String fieldName, ObjectNode objectNode,
                                           JsonNode oldValue, JsonNode newValue)
          throws JsonProcessingException
      {
          // By default, we don't do anything
          ;
      }
  
      /**
       * Method called when there is a duplicate value for a field.
       * By default we don't care, and the last value is used.
       * Can be overridden to provide alternate handling, such as throwing
       * an exception, or choosing different strategy for combining values
       * or choosing which one to keep.
       *
       * @param fieldName Name of the field for which duplicate value was found
       * @param objectNode Object node that contains values
       * @param oldValue Value that existed for the object node before newValue
       *   was added
       * @param newValue Newly added value just added to the object node
       */
      protected void _handleDuplicateField(JsonParser jp, DeserializationContext ctxt,
              JsonNodeFactory nodeFactory,
              String fieldName, ObjectNode objectNode,
              JsonNode oldValue, JsonNode newValue)
          throws JsonProcessingException
      {
          // [Issue#237]: Report an error if asked to do so:
          if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY)) {
              _reportProblem(jp, "Duplicate field '"+fieldName+"' for ObjectNode: not allowed when FAIL_ON_READING_DUP_TREE_KEY enabled");
          }
          // Backwards-compatibility; call in case it's overloaded
          _handleDuplicateField(fieldName, objectNode, oldValue, newValue);
      }
  
      /*
      /**********************************************************
      /* Helper methods
      /**********************************************************
       */
  
      protected final ObjectNode deserializeObject(JsonParser jp, DeserializationContext ctxt,
              final JsonNodeFactory nodeFactory) throws IOException
      {
  