Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serializer and parser with inheritance #3

Closed
unoexperto opened this issue Oct 22, 2020 · 1 comment
Closed

Serializer and parser with inheritance #3

unoexperto opened this issue Oct 22, 2020 · 1 comment
Assignees

Comments

@unoexperto
Copy link

Could you please provide examples of serializer and parser for following hierarchy ?

interface Base2
data class One(val value: String) : Base2
data class Two(val value: Long) : Base2

I guess serializer could look like this

    val ser = JsonSerializer.create().withSerializer(Base2::class.java, TypeJsonSerializer<Base2> { ctx, value ->
        ctx.writeOpenArray()
        when (value) {
            is One -> {
                ctx.writeNumber(1)
                ctx.writeComma()
                ctx.writeString(value.value)
            }
            is Two -> {
                ctx.writeNumber(2)
                ctx.writeComma()
                ctx.writeNumber(value.value)
            }
            else -> {
            }
        }
        ctx.writeCloseArray()
        true
    })

but what about deserializer for I can properly deserialize List<Base2> ?

@igr igr self-assigned this Oct 23, 2020
@igr
Copy link
Member

igr commented Oct 23, 2020

Hey! You have multiple options! 3 are with regular JsonSerializer, one with the custom one.

1. Using type information metadata

You don't need to do anything specific here - the types information is stored within the JSON:

final List<Base2> list = new ArrayList<>();
list.add(new One());
list.add(new Two());

String json = JsonSerializer.create().withClassMetadata(true).serialize(list);
List<Base2> listout = JsonParser.create().withClassMetadata(true).parse(json);

assertEquals(2, listout.size());
assertTrue(listout.get(0) instanceof One);
assertTrue(listout.get(1) instanceof Two);

2. Don't use anything

Jodd tries to do its best! Look:

public static class Holder {
	private List<One> ones = new ArrayList<>();
	private List<Two> twos = new ArrayList<>();
}

// ...

final JsonSerializer s = JsonSerializer.create();

final Holder holder = new Holder();
holder.getOnes().add(new One());
holder.getTwos().add(new Two());

final String json = s.deep(true).serialize(holder);

assertEquals("{\"ones\":[{\"value\":\"one\"}],\"twos\":[{\"value\":222}]}", json);

final Holder holderOut = JsonParser.create().useAltPaths()
		.map("ones.values", One.class)
		.map("Two.values", Two.class)
		.parse(json, Holder.class);

assertEquals(1, holderOut.getOnes().size());
assertTrue(holderOut.getOnes().get(0) instanceof One);
assertEquals(1, holderOut.getTwos().size());
assertTrue(holderOut.getTwos().get(0) instanceof Two);

Simply because we have the Holder, Jodd can figure out the types.

3. Use alt paths

Again, serialize using default JsonSerializer. Now, when there is no type information in the object, like a simple List, you can use alternative paths:

final JsonSerializer s = JsonSerializer.create();

final List<Base2> list = new ArrayList<>();
list.add(new One());
list.add(new Two());

final String json = s.serialize(list);
assertEquals("[{\"value\":\"one\"},{\"value\":222}]", json);

final List<Base2> listOut = JsonParser.create()
		.useAltPaths()
		.map("values[0]", One.class)
		.map("values[1]", Two.class)
		.parse(json);

assertNotNull(listOut);

See here

4. Use specific Serializer

You made a specific serializer, and the serialization works. For deserialization, you would need a custom ValueConverter registered with the parser. However, Jodd needs more work here (see #2).

This is the code that should work, but it doesn't (yet):

final List<Base2> listOut = JsonParser.create()
.withValueConverter("values", new ValueConverter() {
	@Override
	public Object convert(final Object source) {
		// CONVERT ARRAY TO SPECIFIC One/Two TYPE.
	}
}).parse(json);

If you insist on the deserialization of custom serialization, I am afraid I need just a bit more work to put in Jodd.

@igr igr closed this as completed Jun 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants