/**
* (C) 2007-2010 Taobao Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
package com.taobao.tair.json;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
public class Json {
private static final int ELEMENT_TYPE_INT = 0;
private static final int ELEMENT_TYPE_LLONG = 1;
private static final int ELEMENT_TYPE_DOUBLE = 2;
private static final int ELEMENT_TYPE_STRING = 3;
public static final int ELEMENT_TYPE_INVALID = 4;
private static final String charset = "UTF-8";
public static byte[] serialize(List<? extends Object> data) {
int type = -1;
if (data == null || data.size() == 0
|| (type = checkType(data)) < 0)
return null;
String str = JSONValue.toJSONString(data);
try {
byte[] bytes = str.getBytes(charset);
int meta = encodeMeta(data.size(), type);
ByteBuffer bb = ByteBuffer.allocate(4 + bytes.length);
bb.putInt(meta);
bb.put(bytes);
return bb.array();
} catch (UnsupportedEncodingException e) {
return null;
}
}
public static List<? extends Object> deSerialize(byte[] source)
throws IOException {
ByteBuffer buffer = ByteBuffer.wrap(source);
int meta = buffer.getInt();
int type = getType(meta);
String value = new String(source, 4, source.length - 4, charset);
switch (type) {
case ELEMENT_TYPE_INT:
List<Integer> resInts = new ArrayList<Integer>();
JSONArray arrayInts = (JSONArray) JSONValue.parse(value);
for (Object object : arrayInts) {
resInts.add(Integer.parseInt(object.toString()));
}
return resInts;
case ELEMENT_TYPE_LLONG:
List<Long> resLongs = new ArrayList<Long>();
JSONArray arrayLongs = (JSONArray) JSONValue.parse(value);
for (Object object : arrayLongs) {
resLongs.add(Long.parseLong(object.toString()));
}
return resLongs;
case ELEMENT_TYPE_DOUBLE:
List<Double> resDoubles = new ArrayList<Double>();
JSONArray arrayDoubles = (JSONArray) JSONValue.parse(value);
for (Object object : arrayDoubles) {
resDoubles.add(Double.parseDouble(object.toString()));
}
return resDoubles;
case ELEMENT_TYPE_STRING:
List<String> results = new ArrayList<String>();
JSONArray arrayString = (JSONArray) JSONValue.parse(value);
for (Object object : arrayString)
results.add((String) object);
return results;
default:
break;
}
return null;
}
public static int checkType(List<? extends Object> elements) {
int firstType = -1;
for (int i=0; i<elements.size(); ++i) {
if (i == 0) {
firstType = checkType(elements.get(i));
if (firstType < 0)
return firstType;
} else {
int type = checkType(elements.get(i));
if (type < 0 || type != firstType) {
return -1;
}
}
}
return firstType;
}
private static int checkType(Object element) {
if (element instanceof Integer)
return ELEMENT_TYPE_INT;
if (element instanceof Long)
return ELEMENT_TYPE_LLONG;
if (element instanceof Double)
return ELEMENT_TYPE_DOUBLE;
if (element instanceof String)
return ELEMENT_TYPE_STRING;
return -1;
}
private static int encodeMeta(int count, int type) {
int result = (type & 0x7) << 16;
result |= (count & 0xFFFF);
return result;
}
@SuppressWarnings("unused")
private static int getCount(int value) {
return value & 0xFFFF;
}
private static int getType(int value) {
return (value >> 16) & 0x7;
}
}