Package com.alibaba.dubbo.common.json

Source Code of com.alibaba.dubbo.common.json.JSON

/*
* Copyright 1999-2011 Alibaba Group.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*      http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.dubbo.common.json;

import java.io.IOException;

import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;

import com.alibaba.dubbo.common.bytecode.Wrapper;
import com.alibaba.dubbo.common.utils.Stack;

/**
* JSON.
*
* @author qian.lei
*/

public class JSON
{
  public static final char LBRACE = '{', RBRACE = '}';

  public static final char LSQUARE = '[', RSQUARE = ']';

  public static final char COMMA = ',', COLON = ':', QUOTE = '"';

  public static final String NULL = "null";

  static final JSONConverter DEFAULT_CONVERTER = new GenericJSONConverter();

  // state.
  public static final byte END = 0, START = 1, OBJECT_ITEM = 2, OBJECT_VALUE = 3, ARRAY_ITEM = 4;

  private static class Entry
  {
    byte state;
    Object value;
    Entry(byte s, Object v){ state = s; value = v; }
  }

  private JSON(){}

  /**
   * json string.
   *
   * @param obj object.
   * @return json string.
   * @throws IOException.
   */
  public static String json(Object obj) throws IOException
  {
    if( obj == null ) return NULL;
    StringWriter sw = new StringWriter();
    try
    {
      json(obj, sw);
      return sw.getBuffer().toString();
    }
    finally{ sw.close(); }
  }

  /**
   * write json.
   *
   * @param obj object.
   * @param writer writer.
   * @throws IOException.
   */
  public static void json(Object obj, Writer writer) throws IOException
    {
      json(obj, writer, false);
    }
 
  public static void json(Object obj, Writer writer, boolean writeClass) throws IOException
  {
    if( obj == null )
      writer.write(NULL);
    else
      json(obj, new JSONWriter(writer), writeClass);
  }

  /**
   * json string.
   *
   * @param obj object.
   * @param properties property name array.
   * @return json string.
   * @throws IOException.
   */
  public static String json(Object obj, String[] properties) throws IOException
  {
    if( obj == null ) return NULL;
    StringWriter sw = new StringWriter();
    try
    {
      json(obj, properties, sw);
      return sw.getBuffer().toString();
    }
    finally{ sw.close(); }
  }
 
  public static void json(Object obj, final String[] properties, Writer writer) throws IOException
    {
      json(obj, properties, writer, false);
    }

  /**
   * write json.
   *
   * @param obj object.
   * @param properties property name array.
   * @param writer writer.
   * @throws IOException.
   */
  public static void json(Object obj, final String[] properties, Writer writer, boolean writeClass) throws IOException
  {
    if( obj == null )
      writer.write(NULL);
    else
      json(obj, properties, new JSONWriter(writer), writeClass);
  }

  private static void json(Object obj, JSONWriter jb, boolean writeClass) throws IOException
  {
    if( obj == null )
      jb.valueNull();
    else
      DEFAULT_CONVERTER.writeValue(obj, jb, writeClass);
  }

  private static void json(Object obj, String[] properties, JSONWriter jb, boolean writeClass) throws IOException
  {
    if( obj == null )
    {
      jb.valueNull();
    }
    else
    {
      Wrapper wrapper = Wrapper.getWrapper(obj.getClass());

      Object value;
      jb.objectBegin();
      for( String prop : properties )
      {
        jb.objectItem(prop);
        value = wrapper.getPropertyValue(obj, prop);
        if( value == null )
          jb.valueNull();
        else
          DEFAULT_CONVERTER.writeValue(value, jb, writeClass);
      }
      jb.objectEnd();
    }
  }

  /**
   * parse json.
   *
   * @param json json source.
   * @return JSONObject or JSONArray or Boolean or Long or Double or String or null
   * @throws ParseException
   */
  public static Object parse(String json) throws ParseException
  {
    StringReader reader = new StringReader(json);
    try{ return parse(reader); }
    catch(IOException e){ throw new ParseException(e.getMessage()); }
    finally{ reader.close(); }
  }

  /**
   * parse json.
   *
   * @param reader reader.
   * @return JSONObject or JSONArray or Boolean or Long or Double or String or null
   * @throws IOException
   * @throws ParseException
   */
  public static Object parse(Reader reader) throws IOException, ParseException
  {
    return parse(reader, JSONToken.ANY);
  }

  /**
   * parse json.
   *
   * @param json json string.
   * @param type target type.
   * @return result.
   * @throws ParseException
   */
  public static <T> T parse(String json, Class<T> type) throws ParseException
  {
    StringReader reader = new StringReader(json);
    try{ return parse(reader, type); }
    catch(IOException e){ throw new ParseException(e.getMessage()); }
    finally{ reader.close(); }
  }

  /**
   * parse json
   *
   * @param reader json source.
   * @param type target type.
   * @return result.
   * @throws IOException
   * @throws ParseException
   */
  @SuppressWarnings("unchecked")
  public static <T> T parse(Reader reader, Class<T> type) throws IOException, ParseException
  {
    return (T)parse(reader, new J2oVisitor(type, DEFAULT_CONVERTER), JSONToken.ANY);
  }

  /**
   * parse json.
   *
   * @param json json string.
   * @param types target type array.
   * @return result.
   * @throws ParseException
   */
  public static Object[] parse(String json, Class<?>[] types) throws ParseException
  {
    StringReader reader = new StringReader(json);
    try{ return (Object[])parse(reader, types); }
    catch(IOException e){ throw new ParseException(e.getMessage()); }
    finally{ reader.close(); }
  }

  /**
   * parse json.
   *
   * @param reader json source.
   * @param types target type array.
   * @return result.
   * @throws IOException
   * @throws ParseException
   */
  public static Object[] parse(Reader reader, Class<?>[] types) throws IOException, ParseException
  {
    return (Object[])parse(reader, new J2oVisitor(types, DEFAULT_CONVERTER), JSONToken.LSQUARE);
  }

  /**
   * parse json.
   *
   * @param json json string.
   * @param handler handler.
   * @return result.
   * @throws ParseException
   */
  public static Object parse(String json, JSONVisitor handler) throws ParseException
  {
    StringReader reader = new StringReader(json);
    try{ return parse(reader, handler); }
    catch(IOException e){ throw new ParseException(e.getMessage()); }
    finally{ reader.close(); }
  }

  /**
   * parse json.
   *
   * @param reader json source.
   * @param handler handler.
   * @return resule.
   * @throws IOException
   * @throws ParseException
   */
  public static Object parse(Reader reader, JSONVisitor handler) throws IOException, ParseException
  {
    return parse(reader, handler, JSONToken.ANY);
  }

  private static Object parse(Reader reader, int expect) throws IOException, ParseException
  {
    JSONReader jr = new JSONReader(reader);
    JSONToken token = jr.nextToken(expect);

    byte state = START;
    Object value = null, tmp;
    Stack<Entry> stack = new Stack<Entry>();

    do
    {
      switch( state )
      {
        case END:
          throw new ParseException("JSON source format error.");
        case START:
        {
          switch( token.type )
          {
            case JSONToken.NULL: case JSONToken.BOOL: case JSONToken.INT: case JSONToken.FLOAT: case JSONToken.STRING:
            {
              state = END;
              value = token.value;
              break;
            }
            case JSONToken.LSQUARE:
            {
              state = ARRAY_ITEM;
              value = new JSONArray();
              break;
            }
            case JSONToken.LBRACE:
            {
              state = OBJECT_ITEM;
              value = new JSONObject();
              break;
            }
            default:
              throw new ParseException("Unexcepted token expect [ VALUE or '[' or '{' ] get '" + JSONToken.token2string(token.type) + "'");
          }
          break;
        }
        case ARRAY_ITEM:
        {
          switch( token.type )
          {
            case JSONToken.COMMA:
              break;
            case JSONToken.NULL: case JSONToken.BOOL: case JSONToken.INT: case JSONToken.FLOAT: case JSONToken.STRING:
            {
              ((JSONArray)value).add(token.value);
              break;
            }
            case JSONToken.RSQUARE: // end of array.
            {
              if( stack.isEmpty() )
              {
                state = END;
              }
              else
              {
                Entry entry = stack.pop();
                state = entry.state;
                value = entry.value;
              }
              break;
            }
            case JSONToken.LSQUARE: // array begin.
            {
              tmp = new JSONArray();
              ((JSONArray)value).add(tmp);
              stack.push(new Entry(state, value));

              state = ARRAY_ITEM;
              value = tmp;
              break;
            }
            case JSONToken.LBRACE: // object begin.
            {
              tmp = new JSONObject();
              ((JSONArray)value).add(tmp);
              stack.push(new Entry(state, value));

              state = OBJECT_ITEM;
              value = tmp;
              break;
            }
            default:
              throw new ParseException("Unexcepted token expect [ VALUE or ',' or ']' or '[' or '{' ] get '" + JSONToken.token2string(token.type) + "'");
          }
          break;
        }
        case OBJECT_ITEM:
        {
          switch( token.type )
          {
            case JSONToken.COMMA:
              break;
            case JSONToken.IDENT: // item name.
            {
              stack.push(new Entry(OBJECT_ITEM, (String)token.value));
              state = OBJECT_VALUE;
              break;
            }
            case JSONToken.NULL:
            {
              stack.push(new Entry(OBJECT_ITEM, "null"));
              state = OBJECT_VALUE;
              break;
            }
            case JSONToken.BOOL: case JSONToken.INT: case JSONToken.FLOAT: case JSONToken.STRING:
            {
              stack.push(new Entry(OBJECT_ITEM, token.value.toString()));
              state = OBJECT_VALUE;
              break;
            }
            case JSONToken.RBRACE: // end of object.
            {
              if( stack.isEmpty() )
              {
                state = END;
              }
              else
              {
                Entry entry = stack.pop();
                state = entry.state;
                value = entry.value;
              }
              break;
            }
            default:
              throw new ParseException("Unexcepted token expect [ IDENT or VALUE or ',' or '}' ] get '" + JSONToken.token2string(token.type) + "'");
          }
          break;
        }
        case OBJECT_VALUE:
        {
          switch( token.type )
          {
            case JSONToken.COLON:
              break;
            case JSONToken.NULL: case JSONToken.BOOL: case JSONToken.INT: case JSONToken.FLOAT: case JSONToken.STRING:
            {
              ((JSONObject)value).put((String)stack.pop().value, token.value);
              state = OBJECT_ITEM;
              break;
            }
            case JSONToken.LSQUARE: // array begin.
            {
              tmp = new JSONArray();
              ((JSONObject)value).put((String)stack.pop().value, tmp);
              stack.push(new Entry(OBJECT_ITEM, value));

              state = ARRAY_ITEM;
              value = tmp;
              break;
            }
            case JSONToken.LBRACE: // object begin.
            {
              tmp = new JSONObject();
              ((JSONObject)value).put((String)stack.pop().value, tmp);
              stack.push(new Entry(OBJECT_ITEM, value));

              state = OBJECT_ITEM;
              value = tmp;
              break;
            }
            default:
              throw new ParseException("Unexcepted token expect [ VALUE or '[' or '{' ] get '" + JSONToken.token2string(token.type) + "'");
          }
          break;
        }
        default:
          throw new ParseException("Unexcepted state.");
      }
    }
    while( ( token = jr.nextToken() ) != null );
    stack.clear();
    return value;
  }

  private static Object parse(Reader reader, JSONVisitor handler, int expect) throws IOException, ParseException
  {
    JSONReader jr = new JSONReader(reader);
    JSONToken token = jr.nextToken(expect);

    Object value = null;
    int state = START, index = 0;
    Stack<int[]> states = new Stack<int[]>();
    boolean pv = false;

    handler.begin();
    do
    {
      switch( state )
      {
        case END:
          throw new ParseException("JSON source format error.");
        case START:
        {
          switch( token.type )
          {
            case JSONToken.NULL:
            {
              value = token.value;
              state = END;
              pv = true;
              break;
            }
            case JSONToken.BOOL:
            {
              value = token.value;
              state = END;
              pv = true;
              break;
            }
            case JSONToken.INT:
            {
              value = token.value;
              state = END;
              pv = true;
              break;
            }
            case JSONToken.FLOAT:
            {
              value = token.value;
              state = END;
              pv = true;
              break;
            }
            case JSONToken.STRING:
            {
              value = token.value;
              state = END;
              pv = true;
              break;
            }
            case JSONToken.LSQUARE:
            {
              handler.arrayBegin();
              state = ARRAY_ITEM;
              break;
            }
            case JSONToken.LBRACE:
            {
              handler.objectBegin();
              state = OBJECT_ITEM;
              break;
            }
            default:
              throw new ParseException("Unexcepted token expect [ VALUE or '[' or '{' ] get '" + JSONToken.token2string(token.type) + "'");
          }
          break;
        }
        case ARRAY_ITEM:
        {
          switch( token.type )
          {
            case JSONToken.COMMA:
              break;
            case JSONToken.NULL:
            {
              handler.arrayItem(index++);
              handler.arrayItemValue(index, token.value, true);
              break;
            }
            case JSONToken.BOOL:
            {
              handler.arrayItem(index++);
              handler.arrayItemValue(index, token.value, true);
              break;
            }
            case JSONToken.INT:
            {
              handler.arrayItem(index++);
              handler.arrayItemValue(index, token.value, true);
              break;
            }
            case JSONToken.FLOAT:
            {
              handler.arrayItem(index++);
              handler.arrayItemValue(index, token.value, true);
              break;
            }
            case JSONToken.STRING:
            {
              handler.arrayItem(index++);
              handler.arrayItemValue(index, token.value, true);
              break;
            }
            case JSONToken.LSQUARE:
            {
              handler.arrayItem(index++);
              states.push(new int[]{state, index});

              index = 0;
              state = ARRAY_ITEM;
              handler.arrayBegin();
              break;
            }
            case JSONToken.LBRACE:
            {
              handler.arrayItem(index++);
              states.push(new int[]{state, index});

              index = 0;
              state = OBJECT_ITEM;
              handler.objectBegin();
              break;
            }
            case JSONToken.RSQUARE:
            {
              if( states.isEmpty() )
              {
                value = handler.arrayEnd(index);
                state = END;
              }
              else
              {
                value = handler.arrayEnd(index);
                int[] tmp = states.pop();
                state = tmp[0];
                index = tmp[1];

                switch( state )
                {
                  case ARRAY_ITEM:
                  {
                    handler.arrayItemValue(index, value, false);
                    break;
                  }
                  case OBJECT_ITEM:
                  {
                    handler.objectItemValue(value, false);
                    break;
                  }
                }
              }
              break;
            }
            default:
              throw new ParseException("Unexcepted token expect [ VALUE or ',' or ']' or '[' or '{' ] get '" + JSONToken.token2string(token.type) + "'");
          }
          break;
        }
        case OBJECT_ITEM:
        {
          switch( token.type )
          {
            case JSONToken.COMMA:
              break;
            case JSONToken.IDENT:
            {
              handler.objectItem((String)token.value);
              state = OBJECT_VALUE;
              break;
            }
            case JSONToken.NULL:
            {
              handler.objectItem("null");
              state = OBJECT_VALUE;
              break;
            }
            case JSONToken.BOOL: case JSONToken.INT: case JSONToken.FLOAT: case JSONToken.STRING:
            {
              handler.objectItem(token.value.toString());
              state = OBJECT_VALUE;
              break;
            }
            case JSONToken.RBRACE:
            {
              if( states.isEmpty() )
              {
                value = handler.objectEnd(index);
                state = END;
              }
              else
              {
                value = handler.objectEnd(index);
                int[] tmp = states.pop();
                state = tmp[0];
                index = tmp[1];

                switch( state )
                {
                  case ARRAY_ITEM:
                  {
                    handler.arrayItemValue(index, value, false);
                    break;
                  }
                  case OBJECT_ITEM:
                  {
                    handler.objectItemValue(value, false);
                    break;
                  }
                }
              }
              break;
            }
            default:
              throw new ParseException("Unexcepted token expect [ IDENT or VALUE or ',' or '}' ] get '" + JSONToken.token2string(token.type) + "'");
          }
          break;
        }
        case OBJECT_VALUE:
        {
          switch( token.type )
          {
            case JSONToken.COLON:
              break;
            case JSONToken.NULL:
            {
              handler.objectItemValue(token.value, true);
              state = OBJECT_ITEM;
              break;
            }
            case JSONToken.BOOL:
            {
              handler.objectItemValue(token.value, true);
              state = OBJECT_ITEM;
              break;
            }
            case JSONToken.INT:
            {
              handler.objectItemValue(token.value, true);
              state = OBJECT_ITEM;
              break;
            }
            case JSONToken.FLOAT:
            {
              handler.objectItemValue(token.value, true);
              state = OBJECT_ITEM;
              break;
            }
            case JSONToken.STRING:
            {
              handler.objectItemValue(token.value, true);
              state = OBJECT_ITEM;
              break;
            }
            case JSONToken.LSQUARE:
            {
              states.push(new int[]{OBJECT_ITEM, index});

              index = 0;
              state = ARRAY_ITEM;
              handler.arrayBegin();
              break;
            }
            case JSONToken.LBRACE:
            {
              states.push(new int[]{OBJECT_ITEM, index});

              index = 0;
              state = OBJECT_ITEM;
              handler.objectBegin();
              break;
            }
            default:
              throw new ParseException("Unexcepted token expect [ VALUE or '[' or '{' ] get '" + JSONToken.token2string(token.type) + "'");
          }
          break;
        }
        default:
          throw new ParseException("Unexcepted state.");
      }
    }
    while( ( token = jr.nextToken() ) != null );
    states.clear();
    return handler.end(value, pv);
  }
}
TOP

Related Classes of com.alibaba.dubbo.common.json.JSON

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.