Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package org.example;
- import java.io.*;
- import java.lang.reflect.*;
- import java.util.*;
- class SimpleSerializer {
- private final Map<Object, Integer> objToId = new IdentityHashMap<>();
- private final Map<Integer, Object> idToObj = new HashMap<>();
- private int nextId = 1;
- // Public API
- public void serialize(Object obj, File file) throws IOException, IllegalAccessException {
- resetState();
- try (PrintWriter out = new PrintWriter(new FileWriter(file))) {
- serializeObject(obj, out);
- }
- }
- public Object deserialize(File file) throws Exception {
- resetState();
- List<String> lines = readAllLines(file);
- createEmptyObjects(lines);
- createArrays(lines);
- setFields(lines);
- setArrayElements(lines);
- return idToObj.get(1);
- }
- private void resetState() {
- objToId.clear();
- idToObj.clear();
- nextId = 1;
- }
- // Serialization
- private void serializeObject(Object obj, PrintWriter out) throws IllegalAccessException {
- if (obj == null) return;
- if (objToId.containsKey(obj)) return; // Already serialized
- int id = nextId++;
- objToId.put(obj, id);
- Class<?> cls = obj.getClass();
- if (cls.isArray()) {
- serializeArray(obj, out, id);
- } else {
- serializeRegularObject(obj, out, id, cls);
- }
- }
- private void serializeArray(Object array, PrintWriter out, int id) throws IllegalAccessException {
- Class<?> compType = array.getClass().getComponentType();
- int length = Array.getLength(array);
- out.printf("arr %d %s %d%n", id, compType.getName(), length);
- for (int i = 0; i < length; i++) {
- Object elem = Array.get(array, i);
- serializeArrayElement(out, id, i, elem, compType);
- }
- }
- private void serializeArrayElement(PrintWriter out, int arrId, int index, Object elem, Class<?> compType) throws IllegalAccessException {
- if (elem == null) {
- out.printf("%d[%d]=null%n", arrId, index);
- } else if (isPrimitiveOrWrapper(compType)) {
- out.printf("%d[%d]=%s%n", arrId, index, elem.toString());
- } else if (compType == String.class) {
- out.printf("%d[%d]=%s%n", arrId, index, escapeString((String) elem));
- } else {
- serializeObject(elem, out);
- int refId = objToId.get(elem);
- out.printf("%d[%d]=ref:%d%n", arrId, index, refId);
- }
- }
- private void serializeRegularObject(Object obj, PrintWriter out, int id, Class<?> cls) throws IllegalAccessException {
- out.printf("obj %d %s%n", id, cls.getName());
- for (Field field : getAllFields(cls)) {
- field.setAccessible(true);
- Object value = field.get(obj);
- serializeField(out, id, field, value);
- }
- }
- private void serializeField(PrintWriter out, int id, Field field, Object value) throws IllegalAccessException {
- if (value == null) {
- out.printf("%d.%s=null%n", id, field.getName());
- return;
- }
- Class<?> type = field.getType();
- if (isPrimitiveOrWrapper(type)) {
- out.printf("%d.%s=%s%n", id, field.getName(), value.toString());
- } else if (type == String.class) {
- out.printf("%d.%s=%s%n", id, field.getName(), escapeString((String) value));
- } else {
- serializeObject(value, out);
- int refId = objToId.get(value);
- out.printf("%d.%s=ref:%d%n", id, field.getName(), refId);
- }
- }
- // Deserialization
- private List<String> readAllLines(File file) throws IOException {
- List<String> lines = new ArrayList<>();
- try (BufferedReader in = new BufferedReader(new FileReader(file))) {
- String line;
- while ((line = in.readLine()) != null) {
- lines.add(line);
- }
- }
- return lines;
- }
- private void createEmptyObjects(List<String> lines) throws Exception {
- for (String line : lines) {
- if (line.startsWith("obj ")) {
- String[] parts = line.split(" ", 3);
- int id = Integer.parseInt(parts[1]);
- String className = parts[2];
- Class<?> cls = Class.forName(className);
- Constructor<?> ctor = cls.getDeclaredConstructor();
- ctor.setAccessible(true);
- Object instance = ctor.newInstance();
- idToObj.put(id, instance);
- }
- }
- }
- private void createArrays(List<String> lines) throws ClassNotFoundException {
- for (String line : lines) {
- if (line.startsWith("arr ")) {
- String[] parts = line.split(" ", 4);
- int id = Integer.parseInt(parts[1]);
- String compTypeName = parts[2];
- int length = Integer.parseInt(parts[3]);
- Class<?> compType = getClassForName(compTypeName);
- Object array = Array.newInstance(compType, length);
- idToObj.put(id, array);
- }
- }
- }
- private void setFields(List<String> lines) throws Exception {
- for (String line : lines) {
- if (line.startsWith("obj ")) continue;
- if (line.startsWith("arr ")) continue;
- if (line.contains("[")) continue; // array elements handled separately
- int dotIndex = line.indexOf('.');
- int eqIndex = line.indexOf('=');
- int id = Integer.parseInt(line.substring(0, dotIndex));
- String fieldName = line.substring(dotIndex + 1, eqIndex);
- String value = line.substring(eqIndex + 1);
- Object obj = idToObj.get(id);
- Class<?> cls = obj.getClass();
- Field field = getField(cls, fieldName);
- field.setAccessible(true);
- setFieldValue(field, obj, value);
- }
- }
- private void setFieldValue(Field field, Object obj, String value) throws Exception {
- Class<?> type = field.getType();
- if (value.equals("null")) {
- field.set(obj, null);
- } else if (isPrimitiveOrWrapper(type)) {
- field.set(obj, parsePrimitive(type, value));
- } else if (type == String.class) {
- field.set(obj, unescapeString(value));
- } else if (value.startsWith("ref:")) {
- int refId = Integer.parseInt(value.substring(4));
- Object refObj = idToObj.get(refId);
- field.set(obj, refObj);
- } else {
- throw new RuntimeException("Unknown value format: " + value);
- }
- }
- private void setArrayElements(List<String> lines) throws Exception {
- for (String line : lines) {
- if (!line.contains("[")) continue;
- int bracketStart = line.indexOf('[');
- int bracketEnd = line.indexOf(']');
- int eqIndex = line.indexOf('=');
- int id = Integer.parseInt(line.substring(0, bracketStart));
- int index = Integer.parseInt(line.substring(bracketStart + 1, bracketEnd));
- String value = line.substring(eqIndex + 1);
- Object array = idToObj.get(id);
- Class<?> compType = array.getClass().getComponentType();
- if (value.equals("null")) {
- Array.set(array, index, null);
- } else if (isPrimitiveOrWrapper(compType)) {
- Array.set(array, index, parsePrimitive(compType, value));
- } else if (compType == String.class) {
- Array.set(array, index, unescapeString(value));
- } else if (value.startsWith("ref:")) {
- int refId = Integer.parseInt(value.substring(4));
- Object refObj = idToObj.get(refId);
- Array.set(array, index, refObj);
- } else {
- throw new RuntimeException("Unknown array element value: " + value);
- }
- }
- }
- // Utility methods
- private List<Field> getAllFields(Class<?> cls) {
- List<Field> fields = new ArrayList<>();
- while (cls != null && cls != Object.class) {
- fields.addAll(Arrays.asList(cls.getDeclaredFields()));
- cls = cls.getSuperclass();
- }
- return fields;
- }
- private Field getField(Class<?> cls, String name) {
- while (cls != null && cls != Object.class) {
- try {
- return cls.getDeclaredField(name);
- } catch (NoSuchFieldException e) {
- cls = cls.getSuperclass();
- }
- }
- throw new RuntimeException("Field not found: " + name);
- }
- private boolean isPrimitiveOrWrapper(Class<?> cls) {
- return cls.isPrimitive() ||
- cls == Integer.class || cls == Long.class || cls == Boolean.class ||
- cls == Byte.class || cls == Character.class || cls == Short.class ||
- cls == Double.class || cls == Float.class;
- }
- private Object parsePrimitive(Class<?> cls, String s) {
- if (cls == int.class || cls == Integer.class) return Integer.parseInt(s);
- if (cls == long.class || cls == Long.class) return Long.parseLong(s);
- if (cls == boolean.class || cls == Boolean.class) return Boolean.parseBoolean(s);
- if (cls == byte.class || cls == Byte.class) return Byte.parseByte(s);
- if (cls == char.class || cls == Character.class) return s.charAt(0);
- if (cls == short.class || cls == Short.class) return Short.parseShort(s);
- if (cls == double.class || cls == Double.class) return Double.parseDouble(s);
- if (cls == float.class || cls == Float.class) return Float.parseFloat(s);
- throw new RuntimeException("Unsupported primitive type: " + cls);
- }
- private Class<?> getClassForName(String name) throws ClassNotFoundException {
- return switch (name) {
- case "int" -> int.class;
- case "long" -> long.class;
- case "boolean" -> boolean.class;
- case "byte" -> byte.class;
- case "char" -> char.class;
- case "short" -> short.class;
- case "double" -> double.class;
- case "float" -> float.class;
- default -> Class.forName(name);
- };
- }
- private String escapeString(String s) {
- return s.replace("\\", "\\\\")
- .replace("\n", "\\n")
- .replace("=", "\\e");
- }
- private String unescapeString(String s) {
- return s.replace("\\e", "=").replace("\\n", "\n").replace("\\\\", "\\");
- }
- }
- public class Main {
- // Test program demonstrating all cases
- public static void main(String[] args) throws Exception {
- var serializer = new SimpleSerializer();
- // Test classes
- class A {
- int x = 10;
- String s = "hello";
- }
- class B extends A {
- double d = 3.14;
- A ref;
- }
- class C {
- int[] arr = {1, 2, 3};
- B b;
- Object[] objs;
- }
- // Create objects with shared references and arrays
- A a1 = new A();
- B b1 = new B();
- b1.ref = a1;
- C c1 = new C();
- c1.b = b1;
- c1.objs = new Object[] {a1, b1, "string", null};
- // Show initial objects
- System.out.println("Original objects:");
- System.out.println("a1: x=" + a1.x + ", s=" + a1.s);
- System.out.println("b1: x=" + b1.x + ", s=" + b1.s + ", d=" + b1.d + ", ref=" + b1.ref);
- System.out.println("c1.arr: " + Arrays.toString(c1.arr));
- System.out.println("c1.b: " + c1.b);
- System.out.println("c1.objs: " + Arrays.toString(c1.objs));
- // Serialize
- File file = new File("test.ser");
- serializer.serialize(c1, file);
- // Deserialize
- Object restored = serializer.deserialize(file);
- C c2 = (C) restored;
- // Show restored objects
- System.out.println("\nRestored objects:");
- System.out.println("c2.arr: " + Arrays.toString(c2.arr));
- System.out.println("c2.b: x=" + c2.b.x + ", s=" + c2.b.s + ", d=" + c2.b.d + ", ref=" + c2.b.ref);
- System.out.println("c2.objs: " + Arrays.toString(c2.objs));
- // Check shared references
- System.out.println("\nShared reference check:");
- System.out.println("c2.b.ref == c2.objs[0]: " + (c2.b.ref == c2.objs[0]));
- // Check array elements
- System.out.println("c2.arr == [1,2,3]: " + Arrays.equals(c2.arr, new int[]{1,2,3}));
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment