How to serialize/deserialize brat Mapping objects?

319 views
Skip to first unread message

Alain Désilets

unread,
Dec 12, 2019, 8:33:54 AM12/12/19
to dkpro-core-user
I need to serialize and deserialize brat Mapping objects. But no matter how much Jacskon black magic I apply, I keep running into troubles during either serialization or deserialization.

Here is a test that illustrates the issue.

@Test
public void test__SerializeDeserializeMapping() throws Exception {
   
List<TypeMapping> textMappingsLst = new ArrayList<TypeMapping>();
   
{
      textMappingsLst
.add(new TypeMapping("PER", Person.class.toString()));
   
}

   
TypeMappings aTextTypeMapppings = new TypeMappings();
   
TypeMappings aRelationTypeMapppings = new TypeMappings();
   
List<SpanMapping> aTextAnnotations = new ArrayList<SpanMapping>();
   
List<RelationMapping> aRelations = new ArrayList<RelationMapping>();
   
List<CommentMapping> aComments = new ArrayList<CommentMapping>();
 
   
Mapping mapping = new Mapping(aTextTypeMapppings, aRelationTypeMapppings,
                             aTextAnnotations
, aRelations, aComments);
   
ObjectMapper mapper = new ObjectMapper();
 
   
// This seems necessary for serializing the Mapping
   mapper
.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);


   
// These are set in BratReader.initialize()
   mapper
.setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY));
   mapper
.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);


   
// Serialization works as long as Visibility.ANY is set
   
//
   
String json = mapper.writeValueAsString(mapping);
   
System.out.println("json="+json);
 
   
// But deserializing the result fails
   
//
   
Mapping readMapping = mapper.readValue(json, Mapping.class);
}


I have to admit I am not familiar with the use of the @JsonProperty annotation. The only Jackson annotation I use is @JsonIgnore, to deal with situations where a method's name starts with get/set eventhough it's not an accessor. 

Richard Eckart de Castilho

unread,
Dec 12, 2019, 8:57:29 AM12/12/19
to dkpro-c...@googlegroups.com
This is the code which the BratReader uses to deserialize:

ObjectMapper mapper = new ObjectMapper();
mapper.setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY));
mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
mapping = mapper.readValue(mappingJson, Mapping.class);

I have not tried serializing them - what trouble do you run into?

Cheers,

-- Richard

Alain Désilets

unread,
Dec 12, 2019, 9:40:46 AM12/12/19
to dkpro-core-user


I have not tried serializing them - what trouble do you run into?

Cheers,

-- Richard

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot create empty instance of [collection type; class java.util.List, contains [simple type, class org.dkpro.core.io.brat.internal.mapping.TypeMapping]], no default Creator
 at [Source: (String)"{"textTypeMapppings":{"parsedMappings":[],"brat2UimaMappingCache":{},"uima2BratMappingCache":{}},"relationTypeMapppings":{"parsedMappings":[],"brat2UimaMappingCache":{},"uima2BratMappingCache":{}},"relations":{},"comments":{"initialListCapacity":3,"empty":true},"textAnnotations":{}}"; line: 1, column: 1]
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1452)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer._findNullProvider(StdDeserializer.java:1103)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.findContentNullProvider(StdDeserializer.java:1062)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.createContextual(CollectionDeserializer.java:192)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.createContextual(CollectionDeserializer.java:27)
at com.fasterxml.jackson.databind.DeserializationContext.handlePrimaryContextualization(DeserializationContext.java:651)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:484)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:293)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
at com.fasterxml.jackson.databind.DeserializationContext.findNonContextualValueDeserializer(DeserializationContext.java:467)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:473)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:293)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:477)
at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:4191)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4010)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3005)
at org.dkpro.core.io.brat.MappingSerializationTest.test__SerializeDeserializeMapping(MappingSerializationTest.java:56)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)


 

Richard Eckart de Castilho

unread,
Dec 12, 2019, 10:43:00 AM12/12/19
to dkpro-c...@googlegroups.com
On 12. Dec 2019, at 15:40, Alain Désilets <alainde...@gmail.com> wrote:
>
> I have not tried serializing them - what trouble do you run into?

This is de-serialization. Try downgrading your jackson to 2.9.10. I think it is a bug in jackson.

-- Richard

Alain Désilets

unread,
Dec 12, 2019, 11:57:56 AM12/12/19
to dkpro-core-user
When I look at the dependency hiearchy in Eclipse, it tells me that I am using 2.9.10. 

Richard Eckart de Castilho

unread,
Dec 13, 2019, 2:46:00 AM12/13/19
to dkpro-c...@googlegroups.com
On 12. Dec 2019, at 17:57, Alain Désilets <alainde...@gmail.com> wrote:
>
> When I look at the dependency hiearchy in Eclipse, it tells me that I am using 2.9.10.

I see this type of error in `BratReaderWriterTest.test1mapping()` the when upgrading the jackson dependencies to 2.10.1:

----
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot create empty instance of [collection type; class java.util.List, contains [simple type, class org.dkpro.core.io.brat.internal.mapping.SpanMapping]], no default Creator
at [Source: (String)"{
'textTypeMapppings': [
{
'from': 'Country',
'to': 'de.tudarmstadt.ukp.dkpro.core.api.ner.type.Location'
},
{
'from': 'Organization',
'to': 'de.tudarmstadt.ukp.dkpro.core.api.ner.type.Organization'
},
{
'from': 'MERGE-ORG',
'to': 'de.tudarmstadt.ukp.dkpro.core.io.brat.type.MergeOrg'
}
],
'relationTypeMapppings': [
{
'from': 'Origin',
'to': 'de.tudarmstadt.ukp.dkpro.core.io.brat.type.AnnotationRelation'
}
],
"[truncated 734 chars]; line: 1, column: 1]
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1589)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer._findNullProvider(StdDeserializer.java:1142)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.findContentNullProvider(StdDeserializer.java:1101)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.createContextual(CollectionDeserializer.java:192)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.createContextual(CollectionDeserializer.java:27)
at com.fasterxml.jackson.databind.DeserializationContext.handlePrimaryContextualization(DeserializationContext.java:650)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:484)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:293)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:476)
at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:4389)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4198)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3205)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3173)
at org.dkpro.core.io.brat.BratReader.initialize(BratReader.java:185)
... 37 more
----

However, with the following jackson dependency versions, the test is fine. Note that there are three relevant dependencies:

----
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.10</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.10</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.10.1</version>
</dependency>
----

The exception being thrown seems to hint at the jackson-databind dependency in particular.

Cheers,

-- Richard

Alain Désilets

unread,
Dec 13, 2019, 9:34:41 AM12/13/19
to dkpro-core-user
I included the Jackson dependancies you recommended at the start of my pom file and I still get the same error.

Note that I tried with with databind set at 2.9.10 instead of 2.9.10.1 (which I assume was a mistake on your part) as well as 2.9.10. 

I attach a small project that illustrates the problem.
BratMappingSerializationIssue.tar.gz

Richard Eckart de Castilho

unread,
Dec 13, 2019, 1:10:35 PM12/13/19
to dkpro-c...@googlegroups.com
On 13. Dec 2019, at 15:34, Alain Désilets <alainde...@gmail.com> wrote:
>
> I included the Jackson dependancies you recommended at the start of my pom file and I still get the same error.
>
> Note that I tried with with databind set at 2.9.10 instead of 2.9.10.1 (which I assume was a mistake on your part) as well as 2.9.10.
>
> I attach a small project that illustrates the problem.

We are talking about the test `test__TODO__FixMappingSerialization()`, right?

Do go get an exception there, but it is a different one from what you reported in your initial mail:

----
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.dkpro.core.io.brat.internal.mapping.TypeMappings and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: org.dkpro.core.io.brat.internal.mapping.Mapping["textTypeMapppings"])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1191)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:313)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:71)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:33)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3906)
at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:3220)
at org.dkpro.core.io.brat.MappingSerializationTest.test__TODO__FixMappingSerialization(MappingSerializationTest.java:57)
----

Is this the exception we are talking about?

-- Richard

Alain Désilets

unread,
Dec 15, 2019, 7:23:15 AM12/15/19
to dkpro-c...@googlegroups.com
Got it!

I just needed to disable FAIL_ON_EMPTY_BEANS:

        mapper.setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY));

        mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);

        mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);


--
You received this message because you are subscribed to a topic in the Google Groups "dkpro-core-user" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/dkpro-core-user/OEsflbzeUzc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to dkpro-core-us...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dkpro-core-user/5387F370-95FF-4F26-AF50-37F5124F5727%40gmail.com.

Richard Eckart de Castilho

unread,
Dec 16, 2019, 9:51:49 AM12/16/19
to dkpro-core-user
On 15. Dec 2019, at 13:23, Alain Désilets <alainde...@gmail.com> wrote:
>
> Got it!
>
> I just needed to disable FAIL_ON_EMPTY_BEANS:
>
> mapper.setDefaultSetterInfo(JsonSetter.Value.forContentNulls(Nulls.AS_EMPTY));
> mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
> mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

Hm... I guess that the proper way of proceeding here would be to tell Jackson how to
serialize TypeMappings. Adding this property disables the error but I guess also means
that the information contained in the TypeMappings objects is not serialized at all.

-- Richard

Alain Désilets

unread,
Dec 16, 2019, 10:55:10 AM12/16/19
to dkpro-c...@googlegroups.com
I have to admit, I have never had this kind of trouble serializing/deserializing objects, but then again, I always use a really simple approach:
 
- Define an empty constructor for the class
- Make all its attributes to be serialized public, or create public setters/getters for them
- Give them an empty value by default (as opposed to null)
- Put @JsonIgnore in front of any method whose name starts with get/set eventhough it's not an accessor

With that approach, most of my serializable classes don't even need to have @JsonXXX annotations at all (unless there are get/set method that are not acessors). And they can be serialized/desiarlized with a default ObjectMapper():

Richard Eckart de Castilho

unread,
Dec 16, 2019, 11:02:18 AM12/16/19
to dkpro-c...@googlegroups.com
On 16. Dec 2019, at 16:54, Alain Désilets <alainde...@gmail.com> wrote:
>
> I have to admit, I have never had this kind of trouble serializing/deserializing objects, but then again, I always use a really simple approach:

I usually build JSON objects differently as well - but in this special case, the ability to read the mappings from JSON was not present from the outset but added later and I wanted to keep the objects compatible with original configuration mechanism. That's why some of the objects may look weird and apparently oddities such as TypeMappings not having a sane serialization yet have crept in.

-- Richard
Reply all
Reply to author
Forward
0 new messages