
com.alibaba.dubbo.common.json.JSON Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dubbo2 Show documentation
Show all versions of dubbo2 Show documentation
The all in one project of dubbo2
The newest version!
/*
* 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 parse(String json, Class 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 parse(Reader reader, Class 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 stack = new Stack();
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 states = new Stack();
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);
}
}