{"id":30536541,"url":"https://github.com/bertilmuth/moonwlker","last_synced_at":"2025-08-27T16:29:45.577Z","repository":{"id":44429256,"uuid":"269786360","full_name":"bertilmuth/moonwlker","owner":"bertilmuth","description":"Jackson JSON without annotation.","archived":false,"fork":false,"pushed_at":"2024-08-05T13:53:21.000Z","size":242,"stargazers_count":28,"open_issues_count":0,"forks_count":6,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-08-06T13:49:41.081Z","etag":null,"topics":["deserialization","jackson","jackson-json","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/bertilmuth.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-06-05T21:47:14.000Z","updated_at":"2024-08-05T13:53:24.000Z","dependencies_parsed_at":"2022-08-20T07:40:40.488Z","dependency_job_id":null,"html_url":"https://github.com/bertilmuth/moonwlker","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bertilmuth/moonwlker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertilmuth%2Fmoonwlker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertilmuth%2Fmoonwlker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertilmuth%2Fmoonwlker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertilmuth%2Fmoonwlker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bertilmuth","download_url":"https://codeload.github.com/bertilmuth/moonwlker/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bertilmuth%2Fmoonwlker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272350831,"owners_count":24919293,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-27T02:00:09.397Z","response_time":76,"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":["deserialization","jackson","jackson-json","java","json","serialization"],"created_at":"2025-08-27T16:29:43.267Z","updated_at":"2025-08-27T16:29:45.565Z","avatar_url":"https://github.com/bertilmuth.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Moonwlker\n[![Gitter](https://badges.gitter.im/requirementsascode/community.svg)](https://gitter.im/requirementsascode/community?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge)\n\nMoonwlker is a facade for the Jackson JSON library.\n\nIt enables you to serialize and deserialize JSON objects without annotations in the classes.\nGetting the Jackson annotations right is challenging, and Moonwlker does the configuration for you under the hood. This way, you can keep your classes free of JSON concerns.\n\nOn top of that, you can serialize and deserialize:\n* immutable objects (without the need for a no-argument constructor, or setters)\n* class hierarchies\n* value types (as custom strings)\n\nYou can also integrate Moonwlker in Spring Boot.\n\n## Getting started\nMoonwlker is available on Maven Central.\n\nIf you are using Maven, include the following in your POM:\n\n``` xml\n\u003cdependency\u003e\n  \u003cgroupId\u003eorg.requirementsascode\u003c/groupId\u003e\n  \u003cartifactId\u003emoonwlker\u003c/artifactId\u003e\n  \u003cversion\u003e0.5.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nIf you are using Gradle, include the following in your build.gradle:\n\n```\nimplementation 'org.requirementsascode:moonwlker:0.5.1'\n```\n\nAt least Java 11 is required, download and install it if necessary.\n\n## Basic usage and defaults\nTo create a Jackson `ObjectMapper` with Moonwlker, use this syntax:\n\n``` java\nimport org.requirementsascode.moonwlker.MoonwlkerModule;\n...\nObjectMapper objectMapper = new ObjectMapper();\nobjectMapper.registerModule(MoonwlkerModule.builder().build());\n```\nThis creates an object mapper that ignores unknown properties when deserializing by default.\n\n## All arguments constructor / immutable objects\nThe standard way in which Jackson supports all arguments constructors is to use the `@JsonCreator` and `@JsonProperties` annotations.\nMoonwlker changes that: it enables you to deserialize objects that have a single, all arguments default constructor. But the class doesn't need to have annotations.\n\nTo enable this feature, you need to pass in the `-parameters` compiler argument when compiling your class files.\nIn Gradle, include this in your build file:\n\n``` Groovy\ngradle.projectsEvaluated {\n tasks.withType(JavaCompile) {\n     options.compilerArgs \u003c\u003c \"-parameters\"\n }\n}\n```\n\n[This article](https://www.concretepage.com/java/jdk-8/java-8-reflection-access-to-parameter-names-of-method-and-constructor-with-maven-gradle-and-eclipse-using-parameters-compiler-argument#compiler-argument) describes how to do that in Maven and your IDE.\n\nAfter you've done that, create an `ObjectMapper` as described in *Basic usage*.\n\nHere's what the example [Dog class](https://github.com/bertilmuth/moonwlker/blob/master/src/test/java/org/requirementsascode/moonwlker/testobject/animal/Dog.java) looks like:\n\n``` java\npublic class Dog extends Animal {\n  private final String name;\n  private final String command;\n\n  public Dog(BigDecimal price, String name, String command) {\n    super(price);\n    this.name = name;\n    this.command = command;\n  }\n  \n  public String name() {\n    return name;\n  }\n\n  public String command() {\n    return command;\n  }\n}\n```\n\nSee [this test class](https://github.com/bertilmuth/moonwlker/blob/master/src/test/java/org/requirementsascode/moonwlker/GeneralTest.java) for details on how to deserialize objects with an all arguments constructor.\n\nNormally, Jackson has special behavior for single argument constructors.\nMoonwlker changes that: it treats single argument constructors the same to simplify deserialization.\n\n## Integrate into Spring Boot application\n\nTo change the default `ObjectMapper` in a Spring Boot application, register the Moonwlker module as a bean:\n\n``` java\n@SpringBootApplication\npublic class GreeterApplication {\n  public static void main(String[] args) {\n    SpringApplication.run(GreeterApplication.class, args);\n  }\n\n  @Bean\n  ObjectMapper objectMapper() {\n    ObjectMapper objectMapper = new ObjectMapper();\n    objectMapper.registerModule(MoonwlkerModule.builder().build());    \n    return objectMapper;\n  } \n}\n```\n\n## (De)serialization of class hierarchies\nBuild your Jackson object mapper with Moonwlker like this:\n\n``` java\nObjectMapper objectMapper = new ObjectMapper();\n\nMoonwlkerModule module =\n  MoonwlkerModule.builder()\n    .fromProperty(\"type\").toSubclassesOf(Person.class)\n    .build();\n\nobjectMapper.registerModule(module);\n```\n\nIn the above example, [Person](https://github.com/bertilmuth/moonwlker/blob/master/src/test/java/org/requirementsascode/moonwlker/testobject/person/Person.java) is the super class.\nThe created `ObjectMapper` (de)serializes objects of direct or indirect subclasses of that super class.\nThe `type` JSON property needs to specify the relative class name of the object to be created by Moonwlker (i.e. [Employee](https://github.com/bertilmuth/moonwlker/blob/master/src/test/java/org/requirementsascode/moonwlker/testobject/person/Employee.java)):\n\n``` java\nString jsonString = \"{\\\"type\\\":\\\"Employee\\\",\\\"firstName\\\":\\\"Jane\\\",\\\"lastName\\\":\\\"Doe\\\",\\\"month\\\":\\\"OCTOBER\\\",\\\"employeeNumber\\\":\\\"EMP-2020\\\"}\";\nEmployee employee = (Employee) objectMapper.readValue(jsonString, Object.class);\n```\nUse a simple class name like above if the sub class is in the same package as the super class.\nUse a package prefix if the sub class is in a direct or indirect sub package of the super class' package. \nFor example, this JSON String could be used if `Employee` was in the `company` subpackage of the package that `Person` is in:\n\n``` java\nString jsonString = \"{\\\"type\\\":\\\"company.Employee\\\",\\\"firstName\\\":\\\"Jane\\\",\\\"lastName\\\":\\\"Doe\\\",\\\"month\\\":\\\"OCTOBER\\\",\\\"employeeNumber\\\":\\\"EMP-2020\\\"}\";\n```\n\nYou can also specify multiple base classes like so:\n\n``` java\nMoonwlkerModule module =\n  MoonwlkerModule.builder()\n    .fromProperty(\"type\").toSubclassesOf(Animal.class, Person.class)\n    .build();\n```\n\nSee [this test class](https://github.com/bertilmuth/moonwlker/blob/master/src/test/java/org/requirementsascode/moonwlker/SubclassInSamePackageTest.java) for details on how to deserialize classes in the same package as their super class.\n\nYou can also define specific packages where subclasses can be found, like so:\n\n``` java\nMoonwlkerModule module = \n  MoonwlkerModule.builder()\n    .fromProperty(\"type\") \n    .toSubclassesOf(Person.class).in(\"org.requirementsascode.moonwlker.testobject.person\")\n    .toSubclassesOf(Animal.class).in(\"org.requirementsascode.moonwlker.testobject.animal\")\n      .build();\n```\n\nSee [this test class](https://github.com/bertilmuth/moonwlker/blob/master/src/test/java/org/requirementsascode/moonwlker/SubclassInSpecifiedPackageTest.java) for details on how to deserialize classes in a specified package.\n\n## Custom (de)serialization of value types\nSometimes you may want to customize the (de)serialization of a value type. \n\nInstead of serializing a value type instance to a JSON object, you rather want to serialize it to an instance of `String`\nor a subclass of `Number`. \n\nLet's have a look at two example classes:\n\n``` java\npublic class ObjectWithJsonValue {\n  private final String someString;\n  private final OrphanAnimal orphanAnimal;\n\n  public ObjectWithJsonValue(String someString, OrphanAnimal orphanAnimal) {\n    this.someString = someString;\n    this.orphanAnimal = orphanAnimal;\n  }\n\n  public String getSomeString() {\n    return someString;\n  }\n\n  public OrphanAnimal getOrphanAnimal() {\n    return orphanAnimal;\n  }\n}\n....\npublic class OrphanAnimal{\n  private final String name;\n\n  public OrphanAnimal(String name) {\n    this.name = name;\n  }\n\n  public String getName() {\n    return name;\n  }\n}\n```\n\nSay you create an instance of `ObjectWithJsonValue` and serialize it:\n\n``` java\nObjectWithJsonValue object = new ObjectWithJsonValue(\"TestString\", new OrphanAnimal(\"PaulTheDog\"));\nString json = objectMapper.writeValueAsString(object);\n```\n\nIf you do this, without custom serialization the `json` String looks like this:\n`{\"someString\":\"TestObject\",\"orphanAnimal\":{\"name\":\"PaulTheDog\"}}`\n\nAs you can see, the orphan animal instance is serialized as a JSON object.\n\nIf you enable custom serialization, the orphan animal instance is instead \"flattened\" to a plain String:\n`{\"someString\":\"TestString\",\"orphanAnimal\":\"PaulTheDog\"}`\n\nTo enable Moonwlker to serialize a value type, you need to provide a function that converts the\nvalue type instance to a String and vice versa:\n\n``` java\nMoonwlkerModule module = MoonwlkerModule.builder()\n  .addStringValueType(OrphanAnimal.class, OrphanAnimal::getName, OrphanAnimal::new)\n  .build();\n```\n\nThe first argument is the value type's class. \n\nThe second argument is a function that converts an instance of the value type to a String.\nMoonwlker uses it for serialization.\n\nThe third argument is the opposite of the second: it's a function that converts a String to a new value type instance.\nMoonwlker uses it for deserialization.\n\nIf you want to serialize to an instance of a subclass of `Number` instead (e.g. `Integer`, `Long` etc.), use the builder method `addNumericValueType()`:\n\n``` java\nMoonwlkerModule module = MoonwlkerModule.builder()\n  .addNumericValueType(Lives.class, Lives::value, Lives::new)\n  .build();\n```\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbertilmuth%2Fmoonwlker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbertilmuth%2Fmoonwlker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbertilmuth%2Fmoonwlker/lists"}