content: package com.alibaba.fastjson2.reader;
  
  import com.alibaba.fastjson2.*;
  import com.alibaba.fastjson2.util.Fnv;
  
  import java.lang.reflect.Type;
  import java.util.Collection;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Map;
  import java.util.function.Supplier;
  
  import static com.alibaba.fastjson2.JSONB.Constants.*;
  
  public final class ObjectReaderImplObject
          extends ObjectReaderPrimitive {
      public static final ObjectReaderImplObject INSTANCE = new ObjectReaderImplObject();
  
      public ObjectReaderImplObject() {
          super(Object.class);
      }
  
      @Override
      public Object createInstance(long features) {
          return new JSONObject();
      }
  
      public Object createInstance(Collection collection, long features) {
          return collection;
      }
  
      @Override
      public Object createInstance(Map map, long features) {
          ObjectReaderProvider provider = JSONFactory.getDefaultObjectReaderProvider();
          Object typeKey = map.get(getTypeKey());
  
          if (typeKey instanceof String) {
              String typeName = (String) typeKey;
              long typeHash = Fnv.hashCode64(typeName);
              ObjectReader reader = null;
              if ((features & JSONReader.Feature.SupportAutoType.mask) != 0) {
                  reader = autoType(provider, typeHash);
              }
  
              if (reader == null) {
                  reader = provider.getObjectReader(
                          typeName, getObjectClass(), features | getFeatures()
                  );
  
                  if (reader == null) {
                      throw new JSONException("No suitable ObjectReader found for" + typeName);
                  }
              }
  
              if (reader != this) {
                  return reader.createInstance(map, features);
              }
          }
  
          return map;
      }
  
      @Override
      public Object readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
          if (jsonReader.jsonb) {
              return jsonReader.readAny();
          }
  
          JSONReader.Context context = jsonReader.getContext();
          long contextFeatures = features | context.getFeatures();
  
          String typeName = null;
          if (jsonReader.isObject()) {
              jsonReader.nextIfObjectStart();
  
              long hash = 0;
              if (jsonReader.isString()) {
                  hash = jsonReader.readFieldNameHashCode();
  
                  if (hash == HASH_TYPE) {
                      boolean supportAutoType = context.isEnabled(JSONReader.Feature.SupportAutoType);
  
                      ObjectReader autoTypeObjectReader;
  
                      if (supportAutoType) {
                          long typeHash = jsonReader.readTypeHashCode();
                          autoTypeObjectReader = context.getObjectReaderAutoType(typeHash);
  
                          if (autoTypeObjectReader != null) {
                              Class objectClass = autoTypeObjectReader.getObjectClass();
                              if (objectClass != null) {
                                  ClassLoader objectClassLoader = objectClass.getClassLoader();
                                  ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
                                  if (objectClassLoader != classLoader) {
                                      Class contextClass = null;
  
                                      typeName = jsonReader.getString();
                                      try {
                                          if (classLoader == null) {
                                              classLoader = getClass().getClassLoader();
                                          }
                                          contextClass = classLoader.loadClass(typeName);
                                      } catch (ClassNotFoundException ignored) {
                                      }
                                      //明确contextClass类型与objectClass不一致时才更改reader
                                      if (contextClass != null && !objectClass.equals(contextClass)) {
                                          autoTypeObjectReader = context.getObjectReader(contextClass);
                                      }
                                  }
                              }
                          }
  
                          if (autoTypeObjectReader == null) {
                              typeName = jsonReader.getString();
                              autoTypeObjectReader = context.getObjectReaderAutoType(typeName, null);
                          }
                      } else {
                          typeName = jsonReader.readString();
                          autoTypeObjectReader = context.getObjectReaderAutoType(typeName, null);
  
                          if (autoTypeObjectReader == null && jsonReader.getContext().isEnabled(JSONReader.Feature.ErrorOnNotSupportAutoType)) {
                              throw new JSONException(jsonReader.info("autoType not support : " + typeName));
                          }
                      }
  
                      if (autoTypeObjectReader != null) {
                          jsonReader.setTypeRedirect(true);
  
                          return autoTypeObjectReader.readObject(jsonReader, fieldType, fieldName, features);
                      }
                  }
              }
  
              Map object;
              Supplier<Map> objectSupplier = jsonReader.getContext().getObjectSupplier();
              if (objectSupplier != null) {
                  object = objectSupplier.get();
              } else {
                  if (((features | context.getFeatures()) & JSONReader.Feature.UseNativeObject.mask) != 0) {
                      object = new HashMap();
                  } else {
                      object = (Map) ObjectReaderImplMap.INSTANCE_OBJECT.createInstance(jsonReader.features(features));
                  }
              }
  
              if (typeName != null) {
                  switch (typeName) {
                      case "java.util.ImmutableCollections$Map1":
                      case "java.util.ImmutableCollections$MapN":
                          break;
                      default:
                          object.put("@type", typeName);
                          break;
                  }
                  hash = 0;
              }
  
              for (int i = 0; ; ++i) {
                  if (jsonReader.nextIfObjectEnd()) {
                      break;
                  }
  
                  if (jsonReader.current() == '/') {
                      jsonReader.skipComment();
                  }
  
                  Object name;
                  if (i == 0 && typeName == null && hash != 0) {
                      name = jsonReader.getFieldName();
                  } else if (jsonReader.isNumber()) {
                      name = jsonReader.readNumber();
                      jsonReader.nextIfMatch(':');
                  } else {
                      name = jsonReader.readFieldName();
                  }
                  if (name == null) {
                      char current = jsonReader.current();
                      if (current == '{' || current == '[') {
                          name = jsonReader.readAny();
                          if (!jsonReader.nextIfMatch(':')) {
                              throw new JSONException(jsonReader.info("illegal input"));
                          }
                      } else {
                          name = jsonReader.readFieldNameUnquote();
                          if (jsonReader.current() == ':') {
                              jsonReader.next();
                          }
                      }
                  }
  
                  Object value;
                  switch (jsonReader.current()) {
                      case '-':
                      case '+':
                      case '0':
                      case '1':
                      case '2':
                      case '3':
                      case '4':
                      case '5':
                      case '6':
                      case '7':
                      case '8':
                      case '9':
                      case '.':
                          value = jsonReader.readNumber();
                          break;
                      case '[':
                          value = jsonReader.readArray();
                          break;
                      case '{':
                          if (jsonReader.isReference()) {
                              String reference = jsonReader.readReference();
                              if ("..".equals(reference)) {
                                  value = object;
                              } else {
                                  jsonReader.addResolveTask(object, name, JSONPath.of(reference));
                                  continue;
                              }
                          } else {
                              value = jsonReader.readObject();
                          }
                          break;
                      case '"':
                      case '\'':
                          value = jsonReader.readString();
                          break;
                      case 't':
                      case 'f':
                          value = jsonReader.readBoolValue();
                          break;
                      case 'n':
                          value = jsonReader.readNullOrNewDate();
                          break;
                      case 'S':
                          if (jsonReader.nextIfSet()) {
                              value = jsonReader.read(HashSet.class);
                          } else {
                              throw new JSONException(jsonReader.info());
                          }
                          break;
                      default:
                          throw new JSONException(jsonReader.info());
                  }
  
                  if (value == null && (contextFeatures & JSONReader.Feature.IgnoreNullPropertyValue.mask) != 0) {
                      continue;
                  }
  
                  Object origin = object.put(name, value);
                  if (origin != null) {
                      if ((contextFeatures & JSONReader.Feature.DuplicateKeyValueAsArray.mask) != 0) {
                          if (origin instanceof Collection) {
                              ((Collection) origin).add(value);
                              object.put(name, origin);
                          } else {
                              JSONArray array = JSONArray.of(origin, value);
                              object.put(name, array);
                          }
                      }
                  }
              }
  
              jsonReader.nextIfComma();
  
              return object;
          }
  
          char ch = jsonReader.current();
          if (ch == '/') {
              jsonReader.skipComment();
              ch = jsonReader.current();
          }
  
          Object value;
          switch (ch) {
              case '-':
              case '+':
              case '0':
              case '1':
              case '2':
              case '3':
              case '4':
              case '5':
              case '6':
              case '7':
              case '8':
              case '9':
              case '.':
                  value = jsonReader.readNumber();
                  break;
              case '[':
                  value = jsonReader.readArray();
                  break;
              case '"':
              case '\'':
                  value = jsonReader.readString();
                  break;
              case 't':
              case 'f':
                  value = jsonReader.readBoolValue();
                  break;
              case 'n':
                  value = jsonReader.readNullOrNewDate();
                  break;
              case 'x':
                  value = jsonReader.readBinary();
                  break;
              case 'S':
                  if (jsonReader.nextIfSet()) {
                      HashSet<Object> set = new HashSet<>();
                      jsonReader.read(set);
                      value = set;
                  } else {
                      throw new JSONException(jsonReader.info());
                  }
                  break;
              default:
                  throw new JSONException(jsonReader.info());
          }
  
          return value;
      }
  
      @Override
      public Object readJSONBObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
          byte type = jsonReader.getType();
          if (type >= BC_STR_ASCII_FIX_MIN && type <= BC_STR_UTF16BE) {
              return jsonReader.readString();
          }
  
          if (type == BC_TYPED_ANY) {
              ObjectReader autoTypeObjectReader = jsonReader.checkAutoType(Object.class, 0, features);
              if (autoTypeObjectReader != null) {
                  return autoTypeObjectReader.readJSONBObject(jsonReader, fieldType, fieldName, features);
              }
          }
  
          if (type == BC_NULL) {
              jsonReader.next();
              return null;
          }
  
          return jsonReader.readAny();
      }
  }
  