emfjson / emfjson-jackson

JSON Binding for Eclipse Modeling Framework
https://emfjson.github.io
Other
80 stars 23 forks source link

Attributes that not setted (with default value) #62

Closed lex-em closed 9 years ago

lex-em commented 9 years ago

Hi, Is it posible to say emfjson do not serialize attributes, that not setted.

In my case I have a stereotype with attribute "messageCasting" (enum type) that not setted. When I serialize this eobject I get json, where attribute is present and setted default value (may be not default, but first in list):

    "messageCasting": {
      "eClass": "http://www.eclipse.org/emf/2002/Ecore#//EEnumLiteral",
      "_id": "_Z1gTXCR_EeW-eZ1ZLTAX7g",
      "name": "UNICAST"
    }

"name": "UNICAST" - It is default value

lex-em commented 9 years ago

Problem with this json occurs when I try to deserialize it. Parser throw exception:

Unrecognized Type: [null]
java.lang.IllegalArgumentException: Unrecognized Type: [null]
    at com.fasterxml.jackson.databind.type.TypeFactory._constructType(TypeFactory.java:405)
    at com.fasterxml.jackson.databind.type.TypeFactory.constructType(TypeFactory.java:354)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1870)
    at com.fasterxml.jackson.core.JsonParser.readValueAs(JsonParser.java:1412)
    at org.emfjson.jackson.databind.deser.EObjectDeserializer.readAttribute(EObjectDeserializer.java:267)
    at org.emfjson.jackson.databind.deser.EObjectDeserializer.readFeature(EObjectDeserializer.java:154)
    at org.emfjson.jackson.databind.deser.EObjectDeserializer.doDeserialize(EObjectDeserializer.java:99)
    at org.emfjson.jackson.databind.deser.EObjectDeserializer.deserialize(EObjectDeserializer.java:61)
    at org.emfjson.jackson.databind.deser.EObjectDeserializer.deserialize(EObjectDeserializer.java:39)
    at com.fasterxml.jackson.databind.DeserializationContext.readPropertyValue(DeserializationContext.java:762)
    at com.fasterxml.jackson.databind.DeserializationContext.readPropertyValue(DeserializationContext.java:750)
    at org.emfjson.jackson.databind.deser.ResourceDeserializer.deserialize(ResourceDeserializer.java:56)
    at org.emfjson.jackson.databind.deser.ResourceDeserializer.deserialize(ResourceDeserializer.java:28)
    at com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1443)
    at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1049)
    at org.emfjson.jackson.resource.JsonResource.doLoad(JsonResource.java:63)
    at org.eclipse.emf.ecore.resource.impl.ResourceImpl.load(ResourceImpl.java:1518)
    at org.eclipse.emf.ecore.resource.impl.ResourceImpl.load(ResourceImpl.java:1297)
    at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.demandLoad(ResourceSetImpl.java:259)
    at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.demandLoadHelper(ResourceSetImpl.java:274)
    at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.getResource(ResourceSetImpl.java:406)
    at com.centreit.repiso.test.TestEmf.test3(TestEmf.java:98)
    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:483)
    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.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    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)

In other case error mesage looks like "Attribute 'name' is not present in type".

When I remove all enum attributes, json data deserialize fine and then save to the same .uml file as original

lex-em commented 9 years ago

Oh, not same file in result, for many other objects appears attribute "visibility" with default value "public"

lex-em commented 9 years ago
    "messageCasting": {
      "eClass": "http://www.eclipse.org/emf/2002/Ecore#//EEnumLiteral",
      "_id": "_Z1gTXCR_EeW-eZ1ZLTAX7g",
      "name": "UNICAST"
    }

This problem occurs when Jackson walk on org.eclipse.emf.ecore.EEnumLiteralImpl inheritance tree, EObject interface finded before Enumerator interface and literal serialize as EObject

lex-em commented 9 years ago

This problem solved when I add next serializer

public class EEnumLiteralSerializer  extends JsonSerializer<EEnumLiteral> {

    private EnumeratorSerializer enumeratorSerializer;

    public EEnumLiteralSerializer(EnumeratorSerializer enumeratorSerializer){
        this.enumeratorSerializer = enumeratorSerializer;
    }

    @Override
    public void serialize(EEnumLiteral eEnumLiteral, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
        enumeratorSerializer.serialize(eEnumLiteral, jsonGenerator, serializerProvider);
    }

    @Override
    public Class<EEnumLiteral> handledType() {
        return EEnumLiteral.class;
    }
}

Now json looks fine:

    "messageCasting": "UNICAST"

But it still not deserialized with the same error. What you think?

ghillairet commented 9 years ago

Can you give me a test case so I can reproduce this, because there is something that does not look right. The emun literal should not be serialized as an object.

lex-em commented 9 years ago

ghillariet, can I do a pull request? Or write here my changes?

ghillairet commented 9 years ago

First, I'd like to reproduce this. If you could make a test that shows the problem or provide me the part of the ecore model that causes the issue, that would help.

lex-em commented 9 years ago

Ok, I give you a test and then do a pull request

lex-em commented 9 years ago

In my case in serialized data I have org.eclipse.emf.ecore.impl.EEnumLiteralImpl object, that extend ENamedElementImpl and implement EEnumLiteral.

Through Jackson search serializer for type it look at classes that extended this type. In this case it is ENamedElementImpl that not realize Enumerator interface, but EObject in root.

Enumerator interface extends by EEnumLiteral interface and Jackson do not look here, because EObject finded before Enumerator in ENamedElementImpl. Do you need tests?

ghillairet commented 9 years ago

Yes I need to see exactly what's in your ecore model.

ghillairet commented 9 years ago

Enumerations are already tested here https://github.com/ghillairet/emfjson/blob/master/emfjson-jackson/src/test/java/org/emfjson/jackson/junit/tests/EnumTest.java

So I need to see what in your case causes the issue.

lex-em commented 9 years ago

here data and test https://drive.google.com/open?id=0B1aHpBKtlMr3dGdzS1BXTENFODQ

ghillairet commented 9 years ago

See #69