Created
July 14, 2016 12:25
-
-
Save jackeylu/3fa72264ca7de02f7030d0ed7b98a3e4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example.protostuff; | |
/** | |
* wrapper is needed for interface and abstract modifier | |
* Created by jackeylv on 2016/7/14. | |
*/ | |
public class ClassWrapper { | |
private Object wrappedValue; | |
public ClassWrapper(){ | |
wrappedValue = null; | |
} | |
public Object getValue() { | |
return wrappedValue; | |
} | |
public void setValue(Object value) { | |
this.wrappedValue = value; | |
} | |
// public Class getRealClass(){ | |
// if (null == value) | |
// return ClassWrapper.class; | |
// | |
// Class clz = value.getClass(); | |
// if (clz.isInterface() | |
// || Modifier.isAbstract(clz.getModifiers())){ | |
// return ClassWrapper.class; | |
// } | |
// | |
// return clz; | |
// } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example.protostuff; | |
import io.protostuff.Input; | |
import io.protostuff.Output; | |
import io.protostuff.Pipe; | |
import io.protostuff.WireFormat; | |
import io.protostuff.runtime.Delegate; | |
import java.io.IOException; | |
import java.sql.Date; | |
/** | |
* Created by jackeylv on 2016/7/14. | |
*/ | |
public class Delegates { | |
public static final Delegate<Date> DATE_DELEGATE = new Delegate<Date>() { | |
public WireFormat.FieldType getFieldType() { | |
return WireFormat.FieldType.FIXED64; | |
} | |
public Date readFrom(Input input) throws IOException { | |
return new Date(input.readFixed64()); | |
} | |
public void writeTo(Output output, int number, Date value, boolean repeated) throws IOException { | |
output.writeFixed64(number, value.getTime(), repeated); | |
} | |
public void transfer(Pipe pipe, Input input, Output output, int number, boolean repeated) throws IOException { | |
output.writeFixed64(number, input.readFixed64(), repeated); | |
} | |
public Class<?> typeClass() { | |
return Date.class; | |
} | |
}; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example.protostuff; | |
import io.protostuff.LinkedBuffer; | |
import io.protostuff.ProtostuffIOUtil; | |
import io.protostuff.Schema; | |
import io.protostuff.runtime.DefaultIdStrategy; | |
import io.protostuff.runtime.RuntimeSchema; | |
import java.util.concurrent.ConcurrentHashMap; | |
/** | |
* Created by jackeylv on 2016/7/14. | |
*/ | |
public class SerializationUtil { | |
private static ConcurrentHashMap<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap(256); | |
private static DefaultIdStrategy strategy = new DefaultIdStrategy(); | |
static { | |
strategy.registerDelegate(Delegates.DATE_DELEGATE); | |
} | |
private static ThreadLocal<ClassWrapper> clazzWrapper = new ThreadLocal<ClassWrapper>(){ | |
@Override | |
protected ClassWrapper initialValue() { | |
return new ClassWrapper(); | |
} | |
}; | |
private SerializationUtil(){} | |
private static Schema getSchema(Class clz){ | |
Schema schema = cachedSchema.get(clz); | |
if (null == schema){ | |
schema = RuntimeSchema.getSchema(clz, strategy); | |
if (null != schema){ | |
cachedSchema.put(clz, schema); | |
} else { | |
throw new IllegalStateException("Failed to create schema for class " + clz); | |
} | |
} | |
return schema; | |
} | |
/** | |
* @param obj | |
* @return | |
*/ | |
public static byte[] marshall(Object obj){ | |
clazzWrapper.get().setValue(obj); | |
LinkedBuffer buffer = LinkedBuffer.allocate(); | |
try { | |
Schema schema = getSchema(ClassWrapper.class); | |
return ProtostuffIOUtil.toByteArray(clazzWrapper.get(), schema, buffer); | |
}finally { | |
buffer.clear(); | |
} | |
} | |
public static Object unmarshall(byte[] bytes){ | |
if (0 == bytes.length) | |
return null; | |
Schema schema = getSchema(ClassWrapper.class); | |
assert null != schema : "schema is null"; | |
ClassWrapper message = (ClassWrapper) schema.newMessage(); | |
ProtostuffIOUtil.mergeFrom(bytes, message, schema); | |
return message.getValue(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package example.protostuff; | |
import example.protostuff.SerializationUtil; | |
import io.protostuff.LinkedBuffer; | |
import io.protostuff.ProtostuffIOUtil; | |
import io.protostuff.Schema; | |
import io.protostuff.runtime.RuntimeSchema; | |
import org.junit.Assert; | |
import org.junit.Test; | |
import java.util.*; | |
import static org.junit.Assert.*; | |
/** | |
* Created by jackeylv on 2016/7/14. | |
*/ | |
public class SerializationUtilTest { | |
private void testHelper(Object obj){ | |
byte[] bytes = SerializationUtil.marshall(obj); | |
System.out.printf("object = %s, object.class = %s, bytes.length = %d, bytes = %s%n", | |
obj, null != obj ? obj.getClass() : null, bytes.length, bytes); | |
Object desr = SerializationUtil.unmarshall(bytes); | |
if (null == obj && null == desr){ | |
return; | |
} | |
if (null == obj && null != desr){ | |
Assert.fail("desc != null"); | |
} | |
if (obj.getClass().isArray()){ | |
System.out.println(Arrays.deepToString((Object[]) obj)); | |
System.out.println(Arrays.deepToString((Object[]) desr)); | |
Assert.assertArrayEquals(((Object[]) obj), ((Object[]) desr)); | |
} else { | |
Assert.assertEquals(obj, desr); | |
} | |
} | |
@Test | |
public void testListWithNullElement() throws Exception { | |
LinkedList lst = new LinkedList(); | |
testHelper(lst); | |
lst.add(1); | |
lst.add("hello"); | |
lst.add("2.456"); | |
testHelper(lst); | |
lst.add(null); | |
lst.add("hi"); | |
testHelper(lst); | |
} | |
@Test | |
public void testSetWithNullElement() throws Exception { | |
HashSet set = null; | |
testHelper(set); | |
set = new HashSet(); | |
testHelper(set); | |
set.add(1); | |
set.add("23"); | |
set.add(null); | |
testHelper(set); | |
} | |
@Test | |
public void testObjectArrayWithNullElements() throws Exception { | |
Object[] objects = new Object[]{ | |
1, null, "hello", null, 345 | |
}; | |
testHelper(objects); | |
} | |
/** | |
* FIXME We can fix it with {@link ClassWrapper}. Or any other suggestions? | |
* java.lang.RuntimeException: The root object can neither be an abstract class nor interface: "[Ljava.lang.Integer; | |
* @throws Exception | |
*/ | |
@Test | |
public void testIntArrayWithRawPS() throws Exception { | |
Integer[] arr = new Integer[]{0,1,2,3}; | |
Schema schema = RuntimeSchema.getSchema(arr.getClass()); | |
LinkedBuffer buffer = LinkedBuffer.allocate(); | |
try { | |
byte[] bytes = ProtostuffIOUtil.toByteArray(arr,schema,buffer); | |
Integer[] ret = (Integer[]) schema.newMessage(); | |
ProtostuffIOUtil.mergeFrom(bytes, ret, schema); | |
Assert.assertArrayEquals(arr, ret); | |
} finally { | |
buffer.clear(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment