content: package com.ruoyi.common.json;
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.LinkedHashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.StringTokenizer;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  import com.fasterxml.jackson.databind.ObjectMapper;
  import com.ruoyi.common.utils.StringUtils;
  
  /**
   * 通用消息对象，基于Map实现的可嵌套数据结构。 支持JSON数据结构。
   * 
   * @author ruoyi
   */
  public class JSONObject extends LinkedHashMap<String, Object>
  {
      private static final long serialVersionUID = 1L;
      private static final Pattern arrayNamePattern = Pattern.compile("(\\w+)((\\[\\d+\\])+)");
      private static final ObjectMapper objectMapper = new ObjectMapper();
  
      /**
       * 数组结构。
       */
      public static class JSONArray extends ArrayList<Object>
      {
          private static final long serialVersionUID = 1L;
  
          public JSONArray()
          {
              super();
          }
  
          public JSONArray(int size)
          {
              super(size);
          }
  
          @Override
          public String toString()
          {
              try
              {
                  return JSON.marshal(this);
              }
              catch (Exception e)
              {
                  throw new RuntimeException(e);
              }
          }
  
          @Override
          public Object set(int index, Object element)
          {
              return super.set(index, transfer(element));
          }
  
          @Override
          public boolean add(Object element)
          {
              return super.add(transfer(element));
          }
  
          @Override
          public void add(int index, Object element)
          {
              super.add(index, transfer(element));
          }
      }
  
      public JSONObject()
      {
          super();
      }
  
      public JSONObject(final JSONObject other)
      {
          super(other);
      }
  
      @Override
      public String toString()
      {
          try
          {
              return JSON.marshal(this);
          }
          catch (Exception e)
          {
              throw new RuntimeException(e);
          }
      }
  
      /**
       * 转换为紧凑格式的字符串。
       * 
       * @return 返回本对象紧凑格式字符串。
       */
      public String toCompactString()
      {
          try
          {
              return objectMapper.writeValueAsString(this);
          }
          catch (Exception e)
          {
              throw new RuntimeException(e);
          }
      }
  
      /**
       * 获取指定字段的整数值。如果字段不存在，或者无法转换为整数，返回null。
       * 
       * @param name 字段名，支持多级。
       * @return 返回指定的整数值，或者null。
       */
      public Integer intValue(final String name)
      {
          return valueAsInt(value(name));
      }
  
      /**
       * 获取指定字段的整数值。如果字段不存在，或者无法转换为整数，返回defaultValue。
       * 
       * @param name 字段名，支持多级。
       * @param defaultValue 查询失败时，返回的值。
       * @return 返回指定的整数值，或者defaultValue。
       */
      public Integer intValue(final String name, final Integer defaultValue)
      {
          return StringUtils.nvl(intValue(name), defaultValue);
      }
  
      /**
       * 获取指定字段的长整数值。如果字段不存在，或者无法转换为长整数，返回null。
       * 
       * @param name 字段名，支持多级。
       * @return 返回指定的长整数值，或者null。
       */
      public Long longValue(final String name)
      {
          return valueAsLong(value(name));
      }
  
      /**
       * 获取指定字段的长整数值。如果字段不存在，或者无法转换为长整数，返回defaultValue。
       * 
       * @param name 字段名，支持多级。
       * @param defaultValue 查询失败时，返回的值。
       * @return 返回指定的长整数值，或者defaultValue。
       */
      public Long longValue(final String name, final Long defaultValue)
      {
          return StringUtils.nvl(longValue(name), defaultValue);
      }
  
      /**
       * 获取指定字段的布尔值。如果字段不存在，或者无法转换为布尔型，返回null。
       * 
       * @param name 字段名，支持多级。
       * @return 返回指定的布尔值，或者null。
       */
      public Boolean boolValue(final String name)
      {
          return valueAsBool(value(name));
      }
  
      /**
       * 获取指定字段的布尔值。如果字段不存在，或者无法转换为布尔型，返回defaultValue。
       * 
       * @param name 字段名，支持多级。
       * @param defaultValue 查询失败时，返回的值。
       * @return 返回指定的布尔值，或者defaultValue。
       */
      public Boolean boolValue(final String name, final Boolean defaultValue)
      {
          return StringUtils.nvl(boolValue(name), defaultValue);
      }
  
      /**
       * 获取指定字段的字符串值。如果字段不存在，返回null。
       * 
       * @param name 字段名，支持多级。
       * @return 返回指定的字符串值，或者null。
       */
      public String strValue(final String name)
      {
          return valueAsStr(value(name));
      }
  
      /**
       * 获取指定字段的字符串值。如果字段不存在，返回defaultValue。
       * 
       * @param name 字段名，支持多级。
       * @param defaultValue 查询失败时，返回的值。
       * @return 返回指定的字符串值，或者defaultValue。
       */
      public String strValue(final String name, final String defaultValue)
      {
          return StringUtils.nvl(strValue(name), defaultValue);
      }
  
      /**
       * 获取指定字段的值。
       * 
       * @param name 字段名，支持多级，支持数组下标。
       * @return 返回指定字段的值。
       */
      public Object value(final String name)
      {
          final int indexDot = name.indexOf('.');
          if (indexDot >= 0)
          {
              return obj(name.substring(0, indexDot)).value(name.substring(indexDot + 1));
          }
          else
          {
              final Matcher matcher = arrayNamePattern.matcher(name);
              if (matcher.find())
              {
                  return endArray(matcher.group(1), matcher.group(2), new EndArrayCallback<Object>()
                  {
                      @Override
                      public Object callback(JSONArray arr, int index)
                      {
                          return elementAt(arr, index);
                      }
                  });
              }
              else
              {
                  return get(name);
              }
          }
      }
  
      /**
       * 设置指定字段的值。
       * 
       * @param name 字段名，支持多级，支持数组下标。
       * @param value 字段值。
       * @return 返回本对象。
       */
      public JSONObject value(final String name, final Object value)
      {
          final int indexDot = name.indexOf('.');
          if (indexDot >= 0)
          {
              obj(name.substring(0, indexDot)).value(name.substring(indexDot + 1), value);
          }
          else
          {
              final Matcher matcher = arrayNamePattern.matcher(name);
              if (matcher.find())
              {
                  endArray(matcher.group(1), matcher.group(2), new EndArrayCallback<Void>()
                  {
                      @Override
                      public Void callback(JSONArray arr, int index)
                      {
                          elementAt(arr, index, value);
                          return null;
                      }
                  });
              }
              else
              {
                  set(name, value);
              }
          }
          return this;
      }
  
      /**
       * 获取对象（非标量类型）字段。返回的数据是一个结构体。当不存在指定对象时，则为指定的名字创建一个空的MessageObject对象。
       * 
       * @param name 字段名。不支持多级名字，支持数组下标。
       * @return 返回指定的对象。如果对象不存在，则为指定的名字创建一个空的MessageObject对象。
       */
      public JSONObject obj(final String name)
      {
          final Matcher matcher = arrayNamePattern.matcher(name);
          if (matcher.find())
          {
              return endArray(matcher.group(1), matcher.group(2), new EndArrayCallback<JSONObject>()
              {
                  @Override
                  public JSONObject callback(JSONArray arr, int index)
                  {
                      return objAt(arr, index);
                  }
              });
          }
          else
          {
              JSONObject obj = getObj(name);
              if (obj == null)
              {
                  obj = new JSONObject();
                  put(name, obj);
              }
              return obj;
          }
      }
  
      /**
       * 获取数组字段。将名字对应的对象以数组对象返回，当指定的字段不存在时，创建一个空的数组。
       * 
       * @param name 字段名。不支持多级名字，不支持下标。
       * @return 返回一个数组（List）。
       */
      public JSONArray arr(final String name)
      {
          JSONArray arr = getArr(name);
          if (arr == null)
          {
              arr = new JSONArray();
              put(name, arr);
          }
          return arr;
      }
  
      /**
       * 获取对象（非标量类型）字段。返回的数据是一个结构体。
       * 
       * @param name 字段名。
       * @return 返回指定的对象字段。
       */
      public JSONObject getObj(final String name)
      {
          return (JSONObject) get(name);
      }
  
      /**
       * 获取数组类型字段。
       * 
       * @param name 字段名。
       * @return 返回数组类型字段。
       */
      public JSONArray getArr(final String name)
      {
          return (JSONArray) get(name);
      }
  
      /**
       * 返回字段整数值。如果不存在，返回null。
       * 
       * @param name 字段名。
       * @return 返回指定字段整数值。
       */
      public Integer getInt(final String name)
      {
          return valueAsInt(get(name));
      }
  
      /**
       * 返回字段整数值。如果不存在，返回defaultValue。
       * 
       * @param name 字段名。
       * @param defaultValue 字段不存在时，返回的值。
       * @return 返回指定字段整数值。
       */
      public Integer getInt(final String name, Integer defaultValue)
      {
          return StringUtils.nvl(getInt(name), defaultValue);
      }
  
      /**
       * 返回字段长整数值。如果不存在，返回null。
       * 
       * @param name 字段名。
       * @return 返回指定字段长整数值。
       */
      public Long getLong(final String name)
      {
          return valueAsLong(get(name));
      }
  
      /**
       * 返回字段长整数值。如果不存在，返回defaultValue。
       * 
       * @param name 字段名。
       * @param defaultValue 字段不存在时，返回的值。
       * @return 返回指定字段长整数值。
       */
      public Long getLong(final String name, Long defaultValue)
      {
          return StringUtils.nvl(getLong(name), defaultValue);
      }
  
      /**
       * 返回字段字符串值。如果不存在，返回null。
       * 
       * @param name 字段名。
       * @return 返回指定字段字符串值。
       */
      public String getStr(final String name)
      {
          return valueAsStr(get(name));
      }
  
      /**
       * 返回字段字符串值。如果不存在，返回defaultValue。
       * 
       * @param name 字段名。
       * @param defaultValue 字段不存在时，返回的值。
       * @return 返回指定字段字符串值。
       */
      public String getStr(final String name, final String defaultValue)
      {
          return StringUtils.nvl(getStr(name), defaultValue);
      }
  
      /**
       * 字段值按照布尔类型返回。如果不存在，返回null。
       * 
       * @param name 字段名。
       * @return 字段值。
       */
      public Boolean getBool(final String name)
      {
          return valueAsBool(get(name));
      }
  
      /**
       * 字段值按照布尔类型返回。如果不存在，返回defaultValue。
       * 
       * @param name 字段名。
       * @param defaultValue 字段不存在时，返回的值。
       * @return 字段值。
       */
      public Boolean getBool(final String name, final Boolean defaultValue)
      {
          return StringUtils.nvl(getBool(name), defaultValue);
      }
  
      /**
       * 设置字段值
       * 
       * @param name 字段名
       * @param value 字段值（标量：数字、字符串、布尔型；结构体：MessageObject）。 如果是Map类型同时非MessageObject类型，则自动转换为MessageObject类型再存入
       *            （此时，再修改Map中的数据，将不会体现到本对象中）。
       * @return 返回本对象
       */
      public JSONObject set(final String name, final Object value)
      {
          put(name, value);
          return this;
      }
  
      /**
       * 将本对象转换为Java Bean。
       * 
       * @param beanClass Java Bean的类对象。
       * @return 返回转换后的Java Bean。
       */
      public <T> T asBean(Class<T> beanClass)
      {
          try
          {
              return JSON.unmarshal(JSON.marshal(this), beanClass);
          }
          catch (Exception e)
          {
              throw new RuntimeException(e);
          }
      }
  
      /**
       * 重载基类的方法。如果 value 是 Map 类型，但不是 MessageObject 类型，则创建一个包含内容等同于原 Map 的 MessageObject 作为 value（注意：此后再更改 Map 的内容，将不会反映到
       * MessageObject 中）。 重载此方法的目的是为了使JSON能够正确地解析为MessageObject对象。不建议直接调用此方法，请使用 set(name, value)方法设置字段值。
       */
      @Override
      public Object put(String key, Object value)
      {
          return super.put(key, transfer(value));
      }
  
      public static Integer valueAsInt(Object value)
      {
          if (value instanceof Integer)
          {
              return (Integer) value;
          }
          else if (value instanceof Number)
          {
              return ((Number) value).intValue();
          }
          else if (value instanceof String)
          {
              return Integer.valueOf((String) value);
          }
          else if (value instanceof Boolean)
          {
              return ((Boolean) value) ? 1 : 0;
          }
          else
          {
              return null;
          }
      }
  
      public static Long valueAsLong(Object value)
      {
          if (value instanceof Long)
          {
              return (Long) value;
          }
          else if (value instanceof Number)
          {
              return ((Number) value).longValue();
          }
          else if (value instanceof String)
          {
              return Long.valueOf((String) value);
          }
          else if (value instanceof Boolean)
          {
              return ((Boolean) value) ? 1L : 0L;
          }
          else
          {
              return null;
          }
      }
  
      public static String valueAsStr(Object value)
      {
          if (value instanceof String)
          {
              return (String) value;
          }
          else if (value != null)
          {
              return value.toString();
          }
          else
          {
              return null;
          }
      }
  
      public static Boolean valueAsBool(Object value)
      {
          if (value instanceof Boolean)
          {
              return (Boolean) value;
          }
          else if (value instanceof Number)
          {
              return ((Number) value).doubleValue() != 0.0;
          }
          else if (value instanceof String)
          {
              return Boolean.valueOf((String) value);
          }
          else
          {
              return null;
          }
      }
  
      /**
       * 将所有层次中凡是Map类型同时又不是MessageObject的类型，转换为MessageObject类型。
       * 
       * @param value 值。
       * @return 返回转换后的值。
       */
      @SuppressWarnings("unchecked")
      private static Object transfer(final Object value)
      {
          if (!(value instanceof JSONObject) && value instanceof Map)
          {
              return toObj((Map<String, Object>) value);
          }
          else if (!(value instanceof JSONArray) && value instanceof Collection)
          {
              return toArr((Collection<Object>) value);
          }
          else
          {
              return value;
          }
      }
  
      private static JSONArray toArr(final Collection<Object> list)
      {
          final JSONArray arr = new JSONArray(list.size());
          for (final Object element : list)
          {
              arr.add(element);
          }
          return arr;
      }
  
      private static JSONObject toObj(final Map<String, Object> map)
      {
          final JSONObject obj = new JSONObject();
          for (final Map.Entry<String, Object> ent : map.entrySet())
          {
              obj.put(ent.getKey(), transfer(ent.getValue()));
          }
          return obj;
      }
  
      /**
       * 将指定下标元素作为数组返回，如果不存在，则在该位置创建一个空的数组。
       * 
       * @param arr 当前数组。
       * @param index 下标。
       * @return 返回当前数组指定下标的元素，该元素应该是一个数组。
       */
      private static JSONArray arrayAt(JSONArray arr, int index)
      {
          expand(arr, index);
          if (arr.get(index) == null)
          {
              arr.set(index, new JSONArray());
          }
          return (JSONArray) arr.get(index);
      }
  
      /**
       * 将指定下标元素作为结构体返回，如果不存在，则在该位置创建一个空的结构体。
       * 
       * @param arr 当前数组。
       * @param index 下标。
       * @return 返回当前数组指定下标元素，该元素是一个结构体。
       */
      private static JSONObject objAt(final JSONArray arr, int index)
      {
          expand(arr, index);
          if (arr.get(index) == null)
          {
              arr.set(index, new JSONObject());
          }
          return (JSONObject) arr.get(index);
      }
  
      /**
       * 设置数组指定下标位置的值。
       * 
       * @param arr 数组。
       * @param index 下标。
       * @param value 值。
       */
      private static void elementAt(final JSONArray arr, final int index, final Object value)
      {
          expand(arr, index).set(index, value);
      }
  
      /**
       * 获取数组指定下标元素的值。
       * 
       * @param arr 数组。
       * @param index 下标。
       * @return 值。
       */
      private static Object elementAt(final JSONArray arr, final int index)
      {
          return expand(arr, index).get(index);
      }
  
      /**
       * 扩展数组到指定下标，以防止访问时下标越界。
       * 
       * @param arr 数组
       * @param index 下标
       * @return 返回传入的数组
       */
      private static JSONArray expand(final JSONArray arr, final int index)
      {
          while (arr.size() <= index)
          {
              arr.add(null);
          }
          return arr;
      }
  
      /**
       * 最后数组回调。
       * 
       * @author Mike
       *
       * @param <T> 回调返回数据类型。
       */
      private interface EndArrayCallback<T>
      {
          /**
           * 当定位到最后一级数组，将调用本方法。
           * 
           * @param arr 最后一级数组对象。
           * @param index 最后一级索引。
           * @return 返回回调的返回值。
           */
          T callback(JSONArray arr, int index);
      }
  
      /**
       * 处理多维数组的工具函数（包括一维数组）。多维数组的名字如：arrary[1][2][3]， 则name=array，indexStr=[1][2][3]，在callback中，endArr将是
       * array[1][2]指定的对象，indexe=3。
       * 
       * @param name 不带下标的名字，不支持多级名字。
       * @param indexesStr 索引部分的字符串，如：[1][2][3]
       * @param callback 回调函数。
       * @return 返回回调函数的返回值。
       */
      private <T> T endArray(final String name, final String indexesStr, final EndArrayCallback<T> callback)
      {
          JSONArray endArr = arr(name);
          final int[] indexes = parseIndexes(indexesStr);
          int i = 0;
          while (i < indexes.length - 1)
          {
              endArr = arrayAt(endArr, indexes[i++]);
          }
          return callback.callback(endArr, indexes[i]);
      }
  
      private static int[] parseIndexes(final String s)
      {
          int[] indexes = null;
          List<Integer> list = new ArrayList<Integer>();
  
          final StringTokenizer st = new StringTokenizer(s, "[]");
          while (st.hasMoreTokens())
          {
              final int index = Integer.valueOf(st.nextToken());
              if (index < 0)
              {
                  throw new RuntimeException(String.format("Illegal index %1$d in \"%2$s\"", index, s));
              }
  
              list.add(index);
          }
  
          indexes = new int[list.size()];
          int i = 0;
          for (Integer tmp : list.toArray(new Integer[list.size()]))
          {
              indexes[i++] = tmp;
          }
  
          return indexes;
      }
  }
  