Howto serialize java.util.Optional and final members

353 views
Skip to first unread message

Sven Rathgeber

unread,
Apr 12, 2019, 7:37:47 AM4/12/19
to SnakeYAML
Hello,

I'm looking for a way to serialize (to yaml) such a class:

public class Person
{
  public final int age;
  public final Optional< String > hairColor;


  public Person(
    int age,
    Optional< String > hairColor )
  {
    this.age = age;
    this.hairColor = hairColor;
  }
}

Is there a way to do that with snakeyaml.

Regards.
Sven

Andrey Somov

unread,
Apr 12, 2019, 10:30:22 AM4/12/19
to snakeya...@googlegroups.com
Hi Sven,

See BeanAccess.FIELD for the variables.

Andrey


--
You received this message because you are subscribed to the Google Groups "SnakeYAML" group.
To unsubscribe from this group and stop receiving emails from it, send an email to snakeyaml-cor...@googlegroups.com.
To post to this group, send email to snakeya...@googlegroups.com.
Visit this group at https://groups.google.com/group/snakeyaml-core.
For more options, visit https://groups.google.com/d/optout.


--
Andrey Somov

Sven Rathgeber

unread,
Apr 13, 2019, 11:54:56 AM4/13/19
to SnakeYAML
Hi Andrey,

thanks for the quick help.

I tried this, but that fails. What am I missing ? I experimented with loadAs(dump, Person.class), but still no success.

 @Test
 
void testYamlSerializationAndDeserialization()
 
{
   
Yaml yaml = new Yaml( new OptionalRepresenter() );
    yaml
.setBeanAccess( BeanAccess.FIELD );
   
Person person = new Person( 101, Optional.of( "green" ) );
   
String dump = yaml.dump(person);
   
System.out.println( dump );
   
Person loadedPerson = yaml.load( dump);
    assertEquals
( person, loadedPerson );
 
}


I get an Exception:
Can't construct a java object for tag:yaml.org,2002:org.yamlstuff.Person; exception=java.lang.InstantiationException: NoSuchMethodException:org.yamlstuff.Person.<init>()
 in 'string', line 1, column 1:
    !!org.yamlstuff.Person

I interpret this, that there is no constructor given. Does snakeyaml expect a default constructor and setter, hmm, but that wouldn't work with final variables.

Do you have any suggestions ?

Regards.
Sven

PS: You can find the complete code here: https://github.com/svenrathgeber/YamlStuff





Am Freitag, 12. April 2019 16:30:22 UTC+2 schrieb Andrey Somov:
Hi Sven,

See BeanAccess.FIELD for the variables.

Andrey


On Fri, Apr 12, 2019 at 2:37 PM Sven Rathgeber <sven.r...@web.de> wrote:
Hello,

I'm looking for a way to serialize (to yaml) such a class:

public class Person
{
  public final int age;
  public final Optional< String > hairColor;


  public Person(
    int age,
    Optional< String > hairColor )
  {
    this.age = age;
    this.hairColor = hairColor;
  }
}

Is there a way to do that with snakeyaml.

Regards.
Sven

--
You received this message because you are subscribed to the Google Groups "SnakeYAML" group.
To unsubscribe from this group and stop receiving emails from it, send an email to snakeya...@googlegroups.com.

To post to this group, send email to snakeya...@googlegroups.com.
Visit this group at https://groups.google.com/group/snakeyaml-core.
For more options, visit https://groups.google.com/d/optout.


--
Andrey Somov

maslovalex

unread,
Apr 14, 2019, 5:13:20 AM4/14/19
to SnakeYAML
Hi Sven,

I think at the moment you would need to have Representer which looks like

public class MyRepresenter extends Representer {
   
public MyRepresenter() {
       
this.representers.put(Optional.class, new RepresentOptional());
       
this.representers.put(Person.class, new RepresentPerson());
   
}

   
private class RepresentOptional implements Represent {

       
@Override
       
public Node representData(Object data) {
           
Optional<?> opt = (Optional<?>) data;
           
List<Object> seq = new ArrayList<>(1);
            seq
.add(opt.get());
           
return representSequence(Tag.SEQ, seq, DumperOptions.FlowStyle.FLOW);
       
}
   
}

   
private class RepresentPerson implements Represent {

       
@Override
       
public Node representData(Object data) {
           
Person person = (Person) data;
           
List<Object> seq = new ArrayList<>(2);
            seq
.add(person.age);
            seq
.add(person.hairColor);
           
return representSequence(Tag.SEQ, seq, DumperOptions.FlowStyle.FLOW);
       
}
   
}
}

If you change your test to use this representer it should work.

-alex

Sven Rathgeber

unread,
Apr 15, 2019, 4:19:49 AM4/15/19
to SnakeYAML
Hi Alex,

thanks for working on a solution.

I tried it and it basically works. Still have to convert List<Object> to Person.

But the main flaw, I see, I'd have to implement each class twice. The class + its Representer.
Whenever class changes I'd have to change the Representer as well. Furthermore this solution
would nail me to snakeyaml and make a library change pretty hard.

That would not work as a general solution for - let's say 1000 classes.

Again, thanks for your help.

Sven


Reply all
Reply to author
Forward
0 new messages