All Projects → bertilmuth → moonwlker

bertilmuth / moonwlker

Licence: Apache-2.0 License
Jackson JSON without annotation.

Programming Languages

java
68154 projects - #9 most used programming language

Projects that are alternatives of or similar to moonwlker

Jackson Module Kotlin
Module that adds support for serialization/deserialization of Kotlin (http://kotlinlang.org) classes and data classes.
Stars: ✭ 830 (+5828.57%)
Mutual labels:  serialization, deserialization, jackson
CodableWrapper
@codec("encoder", "decoder") var cool: Bool = true
Stars: ✭ 143 (+921.43%)
Mutual labels:  serialization, deserialization
nason
🗜 Ultra tiny serializer / encoder with plugin-support. Useful to build binary files containing images, strings, numbers and more!
Stars: ✭ 30 (+114.29%)
Mutual labels:  serialization, deserialization
kafka-protobuf-serde
Serializer/Deserializer for Kafka to serialize/deserialize Protocol Buffers messages
Stars: ✭ 52 (+271.43%)
Mutual labels:  serialization, deserialization
AvroConvert
Apache Avro serializer for .NET
Stars: ✭ 44 (+214.29%)
Mutual labels:  serialization, deserialization
avrow
Avrow is a pure Rust implementation of the avro specification https://avro.apache.org/docs/current/spec.html with Serde support.
Stars: ✭ 27 (+92.86%)
Mutual labels:  serialization, deserialization
dataclasses-jsonschema
JSON schema generation from dataclasses
Stars: ✭ 145 (+935.71%)
Mutual labels:  serialization, deserialization
kafka-serde-scala
Implicitly converts typeclass encoders to kafka Serializer, Deserializer, Serde.
Stars: ✭ 52 (+271.43%)
Mutual labels:  serialization, jackson
schema-gen
XML Schema code generator outputting Swift, Kotlin and Java
Stars: ✭ 25 (+78.57%)
Mutual labels:  serialization, jackson
jzon
A correct and safe JSON parser.
Stars: ✭ 78 (+457.14%)
Mutual labels:  serialization, deserialization
better-serializer
General serializer for PHP. An alternative to JmsSerializer.
Stars: ✭ 27 (+92.86%)
Mutual labels:  deserialization, jackson
NBT
A java implementation of the NBT protocol, including a way to implement custom tags.
Stars: ✭ 128 (+814.29%)
Mutual labels:  serialization, deserialization
cattrs
Complex custom class converters for attrs.
Stars: ✭ 565 (+3935.71%)
Mutual labels:  serialization, deserialization
parco
🏇🏻 generalist, fast and tiny binary parser and compiler generator, powered by Go 1.18+ Generics
Stars: ✭ 57 (+307.14%)
Mutual labels:  serialization, deserialization
serde
🚝 (unmaintained) A framework for defining, serializing, deserializing, and validating data structures
Stars: ✭ 49 (+250%)
Mutual labels:  serialization, deserialization
VSerializer
A library to serialize and deserialize objects with minimum memory usage.
Stars: ✭ 25 (+78.57%)
Mutual labels:  serialization, deserialization
dataconf
Simple dataclasses configuration management for Python with hocon/json/yaml/properties/env-vars/dict support.
Stars: ✭ 40 (+185.71%)
Mutual labels:  serialization, deserialization
json struct
json_struct is a single header only C++ library for parsing JSON directly to C++ structs and vice versa
Stars: ✭ 279 (+1892.86%)
Mutual labels:  serialization, deserialization
sexp-grammar
Invertible parsing for S-expressions
Stars: ✭ 28 (+100%)
Mutual labels:  serialization, deserialization
tyson
A TypeScript serialization/deserialization library to convert objects to/from JSON
Stars: ✭ 25 (+78.57%)
Mutual labels:  serialization, deserialization

Moonwlker

Gitter

Moonwlker is a facade for the Jackson JSON library.

It enables you to serialize and deserialize JSON objects without annotations in the classes. Getting 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.

On top of that, you can serialize and deserialize:

  • immutable objects (without the need for a no-argument constructor, or setters)
  • class hierarchies
  • value types (as custom strings)

You can also integrate Moonwlker in Spring Boot.

Getting started

Moonwlker is available on Maven Central.

If you are using Maven, include the following in your POM:

<dependency>
  <groupId>org.requirementsascode</groupId>
  <artifactId>moonwlker</artifactId>
  <version>0.4</version>
</dependency>

If you are using Gradle, include the following in your build.gradle:

implementation 'org.requirementsascode:moonwlker:0.4'

At least Java 8 is required, download and install it if necessary.

Basic usage and defaults

To create a Jackson ObjectMapper with Moonwlker, use this syntax:

import org.requirementsascode.moonwlker.MoonwlkerModule;
...
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(MoonwlkerModule.builder().build());

This creates an object mapper that ignores unknown properties when deserializing by default.

All arguments constructor / immutable objects

The standard way in which Jackson supports all arguments constructors is to use the @JsonCreator and @JsonProperties annotations. Moonwlker 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.

To enable this feature, you need to pass in the -parameters compiler argument when compiling your class files. In Gradle, include this in your build file:

gradle.projectsEvaluated {
 tasks.withType(JavaCompile) {
     options.compilerArgs << "-parameters"
 }
}

This article describes how to do that in Maven and your IDE.

After you've done that, create an ObjectMapper as described in Basic usage.

Here's what the example Dog class looks like:

public class Dog extends Animal {
  private final String name;
  private final String command;

  public Dog(BigDecimal price, String name, String command) {
    super(price);
    this.name = name;
    this.command = command;
  }
  
  public String name() {
    return name;
  }

  public String command() {
    return command;
  }
}

See this test class for details on how to deserialize objects with an all arguments constructor.

Normally, Jackson has special behavior for single argument constructors. Moonwlker changes that: it treats single argument constructors the same to simplify deserialization.

Integrate into Spring Boot application

To change the default ObjectMapper in a Spring Boot application, register the Moonwlker module as a bean:

@SpringBootApplication
public class GreeterApplication {
  public static void main(String[] args) {
    SpringApplication.run(GreeterApplication.class, args);
  }

  @Bean
  ObjectMapper objectMapper() {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.registerModule(MoonwlkerModule.builder().build());    
    return objectMapper;
  } 
}

(De)serialization of class hierarchies

Build your Jackson object mapper with Moonwlker like this:

ObjectMapper objectMapper = new ObjectMapper();

MoonwlkerModule module =
  MoonwlkerModule.builder()
    .fromProperty("type").toSubclassesOf(Person.class)
    .build();

objectMapper.registerModule(module);

In the above example, Person is the super class. The created ObjectMapper (de)serializes objects of direct or indirect subclasses of that super class. The type JSON property needs to specify the relative class name of the object to be created by Moonwlker (i.e. Employee):

String jsonString = "{\"type\":\"Employee\",\"firstName\":\"Jane\",\"lastName\":\"Doe\",\"month\":\"OCTOBER\",\"employeeNumber\":\"EMP-2020\"}";
Employee employee = (Employee) objectMapper.readValue(jsonString, Object.class);

Use a simple class name like above if the sub class is in the same package as the super class. Use a package prefix if the sub class is in a direct or indirect sub package of the super class' package. For example, this JSON String could be used if Employee was in the company subpackage of the package that Person is in:

String jsonString = "{\"type\":\"company.Employee\",\"firstName\":\"Jane\",\"lastName\":\"Doe\",\"month\":\"OCTOBER\",\"employeeNumber\":\"EMP-2020\"}";

You can also specify multiple base classes like so:

MoonwlkerModule module =
  MoonwlkerModule.builder()
    .fromProperty("type").toSubclassesOf(Animal.class, Person.class)
    .build();

See this test class for details on how to deserialize classes in the same package as their super class.

You can also define specific packages where subclasses can be found, like so:

MoonwlkerModule module = 
  MoonwlkerModule.builder()
    .fromProperty("type") 
    .toSubclassesOf(Person.class).in("org.requirementsascode.moonwlker.testobject.person")
    .toSubclassesOf(Animal.class).in("org.requirementsascode.moonwlker.testobject.animal")
      .build();

See this test class for details on how to deserialize classes in a specified package.

Custom (de)serialization of value types

Sometimes you may want to customize the (de)serialization of a value type.

Instead of serializing a value type instance to a JSON object, you rather want to serialize it to an instance of String or a subclass of Number.

Let's have a look at two example classes:

public class ObjectWithJsonValue {
  private final String someString;
  private final OrphanAnimal orphanAnimal;

  public ObjectWithJsonValue(String someString, OrphanAnimal orphanAnimal) {
    this.someString = someString;
    this.orphanAnimal = orphanAnimal;
  }

  public String getSomeString() {
    return someString;
  }

  public OrphanAnimal getOrphanAnimal() {
    return orphanAnimal;
  }
}
....
public class OrphanAnimal{
  private final String name;

  public OrphanAnimal(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }
}

Say you create an instance of ObjectWithJsonValue and serialize it:

ObjectWithJsonValue object = new ObjectWithJsonValue("TestString", new OrphanAnimal("PaulTheDog"));
String json = objectMapper.writeValueAsString(object);

If you do this, without custom serialization the json String looks like this: {"someString":"TestObject","orphanAnimal":{"name":"PaulTheDog"}}

As you can see, the orphan animal instance is serialized as a JSON object.

If you enable custom serialization, the orphan animal instance is instead "flattened" to a plain String: {"someString":"TestString","orphanAnimal":"PaulTheDog"}

To enable Moonwlker to serialize a value type, you need to provide a function that converts the value type instance to a String and vice versa:

MoonwlkerModule module = MoonwlkerModule.builder()
  .addStringValueType(OrphanAnimal.class, OrphanAnimal::getName, OrphanAnimal::new)
  .build();

The first argument is the value type's class.

The second argument is a function that converts an instance of the value type to a String. Moonwlker uses it for serialization.

The third argument is the opposite of the second: it's a function that converts a String to a new value type instance. Moonwlker uses it for deserialization.

If you want to serialize to an instance of a subclass of Number instead (e.g. Integer, Long etc.), use the builder method addNumericValueType():

MoonwlkerModule module = MoonwlkerModule.builder()
  .addNumericValueType(Lives.class, Lives::value, Lives::new)
  .build();
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].