Я бы использовал простой интерфейс, подобный этому:
public interface Serializer{
public <T> T deserialize(String serializedData);
public String serialize(Object data);
}
И перечисление для его реализации:
public enum StandardSerializer implements Serializer{
INTEGER("I", Integer.class, int.class){
@Override
protected Integer doDeserialize(final String stripped){
return Integer.valueOf(stripped);
}
},
STRING("I", String.class){
@Override
protected Object doDeserialize(final String stripped){
return stripped;
}
},
LIST("L", List.class){
@Override
protected String doSerialize(final Object data){
final Iterator<?> it = ((List<?>) ((List<?>) data)).iterator();
final StringBuilder sb = new StringBuilder();
if(it.hasNext()){
Object next = it.next();
sb.append(StandardSerializer
.forType(next.getClass())
.serialize(next));
while(it.hasNext()){
sb.append(',');
next = it.next();
sb.append(StandardSerializer
.forType(next.getClass())
.serialize(next));
}
}
return sb.toString();
}
@Override
protected Object doDeserialize(final String stripped){
final List<Object> list = new ArrayList<Object>();
for(final String item : stripped.split(",")){
list.add(StandardSerializer.forData(item).deserialize(item));
}
return list;
}
}
/* feel free to implement more enum entries */
;
private static final String DELIMITER = ":";
public static StandardSerializer forType(final Class<?> type){
for(final StandardSerializer candidate : values()){
for(final Class<?> supportedType : candidate.supportedClasses){
if(supportedType.isAssignableFrom(type)) return candidate;
}
}
throw new IllegalArgumentException("Unmapped type: " + type);
}
private final String prefix;
private final Class<?>[] supportedClasses;
private StandardSerializer(final String prefix,
final Class<?>... supportedClasses){
this.prefix = prefix;
this.supportedClasses = supportedClasses;
}
private String base64decode(final String removePrefix){
// TODO call one of the many base64 libraries here
return null;
}
private String base64encode(final String data){
// TODO call one of the many base64 libraries here
return null;
}
@SuppressWarnings("unchecked")
@Override
public final <T> T deserialize(final String serializedData){
return (T) doDeserialize(base64decode(removePrefix(serializedData)));
}
public static StandardSerializer forData(final String serializedData){
final String prefix =
serializedData.substring(0, serializedData.indexOf(DELIMITER));
for(final StandardSerializer candidate : values()){
if(candidate.prefix.equals(prefix)) return candidate;
}
throw new IllegalArgumentException("Unknown prefix: " + prefix);
}
protected abstract Object doDeserialize(String strippedData);
private String removePrefix(final String serializedData){
return serializedData.substring(prefix.length() + DELIMITER.length());
}
// default implementation calles toString()
protected String doSerialize(final Object data){
return data.toString();
}
@Override
public String serialize(final Object data){
return new StringBuilder()
.append(prefix)
.append(DELIMITER)
.append(base64encode(doSerialize(data)))
.toString();
}
}
Теперь вот как вы можете кодировать против этого:
List<?> list = Arrays.asList("abc",123);
String serialized = StandardSerializer.forType(list.getClass()).serialize(list);
List<?> unserialized = StandardSerializer.forData(serialized)
.deserialize(serialized);
(Хотя вы можете выбрать другой формат для сериализации, использование шаблона стратегии enum, вероятно, все еще хорошая идея)