{"id":37024068,"url":"https://github.com/realtimetech-solution/opack","last_synced_at":"2026-01-14T02:54:16.689Z","repository":{"id":42042040,"uuid":"434443893","full_name":"realtimetech-solution/opack","owner":"realtimetech-solution","description":"Fast object or data serialize and deserialize library","archived":false,"fork":false,"pushed_at":"2025-03-17T09:35:24.000Z","size":888,"stargazers_count":28,"open_issues_count":1,"forks_count":3,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-03-17T10:39:11.213Z","etag":null,"topics":["cloning","java","json","serialization"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/realtimetech-solution.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-03T02:40:42.000Z","updated_at":"2025-03-17T09:34:52.000Z","dependencies_parsed_at":"2022-09-26T22:00:26.609Z","dependency_job_id":"f9447adb-d4c8-412f-a0fb-cb2b4a943308","html_url":"https://github.com/realtimetech-solution/opack","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/realtimetech-solution/opack","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/realtimetech-solution%2Fopack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/realtimetech-solution%2Fopack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/realtimetech-solution%2Fopack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/realtimetech-solution%2Fopack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/realtimetech-solution","download_url":"https://codeload.github.com/realtimetech-solution/opack/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/realtimetech-solution%2Fopack/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408795,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T01:52:23.358Z","status":"online","status_checked_at":"2026-01-14T02:00:06.678Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cloning","java","json","serialization"],"created_at":"2026-01-14T02:54:15.799Z","updated_at":"2026-01-14T02:54:16.674Z","avatar_url":"https://github.com/realtimetech-solution.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\" style=\"max-width: 100%; font-weight: bold;\"\u003e\n  \u003ca href=\"https://github.com/realtimetech-solution/opack\"\u003e\u003cimg width=\"100px\" src=\".readme/logo.png\" style=\"max-width: 100%;\" alt=\"logo\"/\u003e\u003c/a\u003e\u003cbr/\u003e\n  Opack\n\u003c/h1\u003e\n\n\u003cp align=\"center\" style=\"max-width: 100%;\"\u003e\n  \u003ca href=\"#\"\u003e\u003cimg src=\"https://img.shields.io/github/license/realtimetech-solution/opack\" alt=\"license\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://maven-badges.herokuapp.com/maven-central/com.realtimetech/opack\"\u003e\u003cimg src=\"https://maven-badges.herokuapp.com/maven-central/com.realtimetech/opack/badge.svg\" alt=\"maven-central-version\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nOpack is a Java library that can serialize/deserialize between Java objects and common objects(OpackValue). Also, common objects can be encoded or decoded as JSON or Bytes(Dense).\n\n**We faster than GSON and Kryo and Jackson.** (See [tests](./src/test/java/com/realtimetech/opack/test/performance))\n\u003cdetails\u003e\n  \u003csummary\u003eClick to see performance benchmark result\u003c/summary\u003e\n\n```\n# GsonPerformanceTest\n\tGson(T)\t: 4441ms\n\tGson(D)\t: 2839ms\n\tOpack  \t: 2756ms\n\n# KryoPerformanceTest\n\tKryo \t: 3110ms\n\tOpack\t: 688ms\n\n# JacksonPerformanceTest\n\tJackson\t: 4626ms\n\tOpack  \t: 3750ms\n```\n\n\u003c/details\u003e\n\n### Simple flow\n\n\u003cp align=\"center\" style=\"max-width: 100%;\"\u003e\n  \u003ca href=\"#\"\u003e\u003cimg width=\"484\" src=\".readme/1_serialize_deserialize.png\" alt=\"sample_1\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\" style=\"max-width: 100%;\"\u003e\n  \u003ca href=\"#\"\u003e\u003cimg width=\"484\" src=\".readme/2_encode_decode.png\" alt=\"sample_2\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n### Download\n\nGradle:\n\n```gradle\ndependencies {\n  implementation 'com.realtimetech:opack:0.2.1'\n}\n```\n\nMaven:\n\n```xml\n\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.realtimetech\u003c/groupId\u003e\n    \u003cartifactId\u003eopack\u003c/artifactId\u003e\n    \u003cversion\u003e0.2.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n### Usage\n\n#### 1. Serialize\n\n```java\npublic class Usage {\n    public static void main(String[] arguments) {\n        Opacker opacker = Opacker.Builder.create().build();\n\n        SomeObject someObject = new SomeObject();\n\n        OpackValue opackValue = opacker.serialize(someObject);\n    }\n}\n```\n\n#### 2. Deserialize\n\n```java\npublic class Usage {\n    public static void main(String[] arguments) {\n        Opacker opacker = Opacker.Builder.create()\n                .setContextStackInitialSize(128)                    // (Optional) Creation size of stack for processing\n                .setValueStackInitialSize(512)                      // (Optional) Creation size of stack for processing\n\n                .setEnableWrapListElementType(false)                // (Optional) When converting elements of a list, record the type as well\n                .setEnableWrapMapElementType(false)                 // (Optional) When converting elements of a map, record the type as well\n                .setEnableConvertEnumToOrdinal(false)               // (Optional) Convert enum to ordinal or name\n                .setEnableConvertRecursiveDependencyToNull(false)   // (Optional) Convert recursive depandency, record null\n\n                .setClassLoader(Usage.class.getClassLoader())       // (Optional) Class loader for processing\n                .build();\n\n        OpackValue serializedSomeObject = null;\n\n        SomeObject someObject = opacker.deserialize(SomeObject.class, serializedSomeObject);\n    }\n}\n```\n\n#### 3. Json Codec\n\n##### General Usage\n\n```java\npublic class Usage {\n    public static void main(String[] arguments) {\n        JsonCodec jsonCodec = JsonCodec.Builder.create()\n                .setEncodeStackInitialSize(128)             // (Optional) Creation size of stack for processing\n                .setEncodeStringBufferSize(1024)            // (Optional) Creation size of stack for processing\n                .setDecodeStackInitialSize(128)             // (Optional) Creation size of stack for processing\n\n                .setAllowAnyValueToKey(false)               // (Optional) Accepts non-string value as Key of Json Object\n                .setEnableConvertCharacterToString(false)   // (Optional) Convert character to string instead of character int value\n                .setUsePrettyFormat(false)                  // (Optional) When encoding, it prints formatted\n\n                .setRoundingMode(RoundingMode.ROUND_EVEN)   // (Optional) Rounding mode to be used for double string conversion\n\n                .build();\n\n        OpackValue opackValue;\n\n        // Encode Basic\n        String json = jsonCodec.encode(opackValue);\n\n        // Encode with Java IO Writer\n        Writer writer;\n        jsonCodec.encode(writer, opackValue);\n\n        // Decode Basic\n        OpackValue decodedOpackValue = jsonCodec.decode(json);\n    }\n}\n```\n\n##### Easy Usage\n\n```java\npublic class Usage {\n    public static void main(String[] arguments) {\n        OpackValue opackValue;\n\n        // Encode\n        String json = Json.encode(opackValue);\n\n        // Decode\n        OpackValue decodedOpackValue = Json.decode(json);\n    }\n}\n```\n\n#### 4. Dense Codec\n\n```java\npublic class Usage {\n    public static void main(String[] arguments) {\n        DenseCodec denseCodec = DenseCodec.Builder.create()\n                .setEncodeStackInitialSize(128)         // (Optional) Creation size of stack for processing\n                .setDecodeStackInitialSize(128)         // (Optional) Creation size of stack for processing\n\n                .setIgnoreVersionCompare(false)         // (Optional) Ignore compare dense codec version in data\n\n                .build();\n\n        OpackValue opackValue;\n\n        // Encode Basic\n        byte[] bytes = denseCodec.encode(opackValue);\n\n        // Encode with Java IO OutputStream\n        OutputStream outputStream;\n        denseCodec.encode(OutputStreamWriter.of(outputStream), opackValue);\n\n        // Encode with ByteArrayWriter\n        ByteArrayWriter byteArrayWriter = new ByteArrayWriter();\n        denseCodec.encode(byteArrayWriter, opackValue);\n        byte[] bytes = byteArrayWriter.toByteArray();\n\n        // Decode Basic\n        OpackValue decodedOpackValue = denseCodec.decode(bytes);\n\n        // Decode with Java IO InputStream\n        InputStream inputStream;\n        OpackValue decodedOpackValue = denseCodec.decode(InputStreamReader.of(inputStream));\n\n        // Decode with ByteArrayReader\n        ByteArrayReader byteArrayReader = new ByteArrayReader(bytes);\n        OpackValue decodedOpackValue = denseCodec.decode(byteArrayReader);\n    }\n}\n```\n\n### Advanced Usage\n\n#### 1. Ignore and Type and Name\n\n```java\npublic class SomeObject {\n    private String stringField;\n    private byte[] bytesField;\n\n    // This field will not serialize/deserialize\n    @Ignore\n    private String verySecretField;\n\n    // This field will serialize/deserialize to explicit type `ArrayList` instead of ambiguous field type `List`\n    @Type(ArrayList.class)\n    private List\u003cString\u003e listField;\n\n    // This field will serialize/deserialize to `newFieldName` name instead of actual field name `oldFieldName`\n    @Name(\"newFieldName\")\n    private String oldFieldName;\n}\n```\n\n#### 2. Field Transformer\n\n```java\npublic class ByteToBase64Transformer implements Transformer {\n    @Override\n    public @Nullable Object serialize(@NotNull Opacker opacker, @NotNull Class\u003c?\u003e originalType, @Nullable Object object) throws SerializeException {\n        if (object instanceof byte[]) {\n            return Base64.getEncoder().encodeToString((byte[]) object);\n        }\n\n        return object;\n    }\n\n    @Override\n    public @Nullable Object deserialize(@NotNull Opacker opacker, @NotNull Class\u003c?\u003e goalType, @Nullable Object object) throws DeserializeException {\n        if (object instanceof String) {\n            return Base64.getDecoder().decode((String) object);\n        }\n\n        return object;\n    }\n}\n\npublic class SomeObject {\n    // This field will serialize/deserialize to Base64\n    @Transform(transformer = ByteToBase64Transformer.class)\n    private byte[] bytesField;\n}\n```\n\n#### 3. Field With Type\n\n```java\npublic class SomeObject {\n    // This field will serialize with runtime type, and deserialize actual type instead of ambiguous field type `List`\n    @WithType\n    private List\u003cString\u003e stringListField;\n\n    // This field will serialize with runtime type, and deserialize actual type instead of ambiguous field type `Object`\n    @WithType\n    private Object[] objectArrayField;\n}\n```\n\n#### 4. Class Transformer\n\n```java\npublic class AnimalTransformer implements Transformer {\n    // Remove a `sound` from a serialized `Animal`\n    @Override\n    public @Nullable Object serialize(@NotNull Opacker opacker, @NotNull Class\u003c?\u003e originalType, @Nullable Object object) throws SerializeException {\n        if (object instanceof Animal) {\n            Animal animal = (Animal) object;\n            OpackValue opackValue = opacker.serialize(animal);\n\n            if (opackValue instanceof OpackObject) {\n                OpackObject opackObject = (OpackObject) opackValue;\n                opackObject.remove(\"sound\");\n                return opackObject;\n            }\n        }\n\n        return object;\n    }\n\n    // Restore `sound` from `Animal` before deserialization\n    @Override\n    public @Nullable Object deserialize(@NotNull Opacker opacker, @NotNull Class\u003c?\u003e goalType, @Nullable Object object) throws DeserializeException {\n        if (object instanceof OpackObject) {\n            if (Animal.class.isAssignableFrom(goalType)) {\n                OpackObject opackObject = (OpackObject) object;\n                Animal animal = (Animal) opacker.deserialize(goalType, opackObject);\n                animal.setSound(animal.bark());\n            }\n        }\n\n        return object;\n    }\n}\n\n// When `inheritable` is set to true, it applies to child classes.\n@Transform(transformer = AnimalTransformer.class, inheritable = true)\nabstract class Animal {\n    private String sound;\n\n    public abstract String bark();\n\n    public String getSound() {\n        return sound;\n    }\n\n    public void setSound(String sound) {\n        this.sound = sound;\n    }\n}\n\npublic class Dog extends Animal {\n    @Override\n    public String bark() {\n        return \"Bow-Wow\";\n    }\n}\n\npublic class SomeObject {\n    private Dog dogField;\n}\n```\n\n#### 5. Handling Opack Value\n\n```java\npublic class Usage {\n    public static void main(String[] arguments) {\n        OpackObject rootObject = new OpackObject();\n\n        {\n            OpackArray opackArray = new OpackArray();\n            opackArray.add(Integer.MAX_VALUE);\n            rootObject.put(\"array\", opackArray);\n        }\n\n        {\n            OpackArray opackArray = OpackArray.createWithArrayObject(new int[]{1, 2, 3, 4, 5, 6});\n            rootObject.put(\"unmodifiable(but, really fast) array\", opackArray);\n        }\n\n        {\n            OpackObject opackObject = new OpackObject();\n            opackObject.put(\"int\", 1);\n            opackObject.put(\"float\", 1.1f);\n            opackObject.put(\"long\", Long.MAX_VALUE);\n            opackObject.put(\"double\", 1.1d);\n\n            opackObject.put(1024, \"2^10\");\n            opackObject.put(\n                    OpackArray.createWithArrayObject(new byte[]{1, 2, 3, 4, 5}),\n                    \"a lot of bytes\"\n            );\n\n            rootObject.put(\"number_map\", opackObject);\n        }\n\n        OpackArray opackArray = (OpackArray) rootObject.get(\"array\");\n        OpackObject opackObject = (OpackObject) rootObject.get(\"number_map\");\n\n        System.out.println(\"1024 is \" + (opackObject.get(1024)));\n        System.out.println(\"Array length is \" + (opackArray.length()));\n        System.out.println(\"First element is \" + (opackArray.get(0)));\n    }\n}\n```\n\n### To-Do\n\n- [ ] Separate field transformer and class transformer\n- [ ] Add generic into the transformer for type safety\n- [ ] Add field pre/post transformer\n- [ ] Remove `fieldTransformer` argument of `Opacker.prepareObjectDeserialize`\n- [ ] Remove `withType` argument of `Opacker.prepareObjectDeserialize`\n\n### License\n\nOpack uses [Apache License 2.0](./LICENSE). Please leave your feedback if you have any suggestions!\n\n```\nJeonghwan, Park\n+821032735003\ndev.parkjeonghwan@gmail.com\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frealtimetech-solution%2Fopack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frealtimetech-solution%2Fopack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frealtimetech-solution%2Fopack/lists"}