EzyFox Binding: Marshal / Unmarshal Data

EzyFox Binding try to provide multi ways to help you marshal and unmarshal data easily.

1. By default

When you provide packages, EzyFox Binding will scan the packages and create reader/writer for which classes that be annotated by EzyArrayBinding and EzyObjectBinding. Example we have 3 classes like this:
package com.tvd12.ezyfox.example.binding.data;

import com.tvd12.ezyfox.binding.annotation.EzyArrayBinding;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@EzyArrayBinding
@AllArgsConstructor
@NoArgsConstructor
public class Author {
    private long id;
    private String name;
}
package com.tvd12.ezyfox.example.binding.data;

import com.tvd12.ezyfox.binding.annotation.EzyObjectBinding;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@EzyObjectBinding
@AllArgsConstructor
@NoArgsConstructor
public class Book {

    private long id;
    private String name;
    private Author author;
    private Category category;
}
package com.tvd12.ezyfox.example.binding.data;

import com.tvd12.ezyfox.binding.annotation.EzyArrayBinding;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@EzyArrayBinding
@AllArgsConstructor
@NoArgsConstructor
public class Category {
    private long id;
    private String name;
}
And then we create a EzyBindingContext like this:
final EzyBindingContext bindingContext = EzyBindingContext.builder()
    .scan("com.tvd12.ezyfox.example.binding")
    .build();
EzyFox Binding will scan the package and create readers/writers for the 3 classes. And then we can marshal and unmarshal the classes without any additional configurations.
final EzyMarshaller marshaller = bindingContext.newMarshaller();
final EzyUnmarshaller unmarshaller = bindingContext.newUnmarshaller();

final EzyObject bookMap = marshaller
    .marshal(
        new Book(
            1,
            "EzyFox in Action",
            new Author(1, "Young Monkeys"),
            new Category(1, "Technical")
        )
    );
System.out.println("bookMap: " + bookMap);

final Book book = unmarshaller.unmarshal(bookMap, Book.class);
System.out.println("book: " + book);

2. Custom Reader / Writer

Sometimes, for some reason, you need to create a customization reader / writer for your data class, Ezyfox Binding will provide to you 3 ways
2.1 Implements EzyTemplate
If your data class need to be marshalled and unmarshalled, you can create a converter and implement it with EzyTemplate, example:
package com.tvd12.ezyfox.example.binding.converter;

import com.tvd12.ezyfox.binding.EzyMarshaller;
import com.tvd12.ezyfox.binding.EzyTemplate;
import com.tvd12.ezyfox.binding.EzyUnmarshaller;
import com.tvd12.ezyfox.binding.annotation.EzyTemplateImpl;
import com.tvd12.ezyfox.entity.EzyArray;
import com.tvd12.ezyfox.example.binding.data.Author;
import com.tvd12.ezyfox.factory.EzyEntityFactory;

@EzyTemplateImpl
public class AuthorConverter
    implements EzyTemplate<EzyArray, Author> {

    @Override
    public Author read(
        EzyUnmarshaller unmarshaller,
        EzyArray array
    ) {
        return new Author(
            array.get(0, long.class),
            array.get(1, String.class)
        );
    }

    @Override
    public EzyArray write(EzyMarshaller marshaller, Author author) {
        return EzyEntityFactory.newArrayBuilder()
            .append(author.getId())
            .append(author.getName())
            .build();
    }
}
2.2 Implements EzyReader
If your data class just need to be unmarshalled, you can create a converter and implement it with EzyReader, example:
package com.tvd12.ezyfox.example.binding.converter;

import com.tvd12.ezyfox.binding.EzyReader;
import com.tvd12.ezyfox.binding.EzyUnmarshaller;
import com.tvd12.ezyfox.binding.annotation.EzyReaderImpl;
import com.tvd12.ezyfox.entity.EzyArray;
import com.tvd12.ezyfox.example.binding.data.Author;

@EzyReaderImpl
public class AuthorReader implements EzyReader<EzyArray, Author> {

    @Override
    public Author read(EzyUnmarshaller unmarshaller, EzyArray array) {
        return new Author(
            array.get(0, long.class),
            array.get(1, String.class)
        );
    }
}
2.3 Implements EzyWriter
If your data class just need to be marshalled, you can create a converter and implement it with EzyWriter, example:
package com.tvd12.ezyfox.example.binding.converter;

import com.tvd12.ezyfox.binding.EzyMarshaller;
import com.tvd12.ezyfox.binding.EzyWriter;
import com.tvd12.ezyfox.binding.annotation.EzyWriterImpl;
import com.tvd12.ezyfox.entity.EzyArray;
import com.tvd12.ezyfox.example.binding.data.Author;
import com.tvd12.ezyfox.factory.EzyEntityFactory;

@EzyWriterImpl
public class AuthorWriter implements EzyWriter<Author, EzyArray> {

    @Override
    public EzyArray write(EzyMarshaller marshaller, Author author) {
        return EzyEntityFactory.newArrayBuilder()
            .append(author.getId())
            .append(author.getName())
            .build();
    }
}

3. Specific Reader / Writer

In some cases, when your data is complicated and you want to specific reader / writer on a field, you can do like this:
package com.tvd12.ezyfox.example.binding.data;

import com.tvd12.ezyfox.binding.annotation.EzyObjectBinding;
import com.tvd12.ezyfox.binding.annotation.EzyReader;
import com.tvd12.ezyfox.binding.annotation.EzyWriter;
import com.tvd12.ezyfox.example.binding.converter.AuthorReader;
import com.tvd12.ezyfox.example.binding.converter.AuthorWriter;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@EzyObjectBinding
@AllArgsConstructor
@NoArgsConstructor
public class Book {

    private long id;
    private String name;
    @EzyReader(AuthorReader.class)
    @EzyWriter(AuthorWriter.class)
    private Author author;
    private Category category;
}