eclipse-emfcloud / emfjson-jackson

emfjson-jackson
Other
16 stars 15 forks source link

EDataTypeDeserializer being called at the wrong time #49

Closed threadedblue closed 1 year ago

threadedblue commented 2 years ago

Consider the following JSON:

{
    "telecom": [
      {
        "system": "phone",         // This a constant in an enum.
        "value": "9786323420" // This is a string
      }
    ],
    "resourceType": "Organization",
    "id": "e44f438a-601b-30fb-85eb-bfaf8ddcb5ad"
}

The value in element telecom.system is an enum constant in the EMF model called: org.hl7.fhir.ContactPointSystemEnum. The value in telecom.value is of type org.hl7.fhir.String

When processing, the deserializer EMFJSON-Jackson attempts to use for telecom.system is EObjectDeserializer; and the deserializer it attempts to use for telecom.value is EDataTypeDeserializer. I hope the problem is obvious, this is backwards. It should be the other way around. Should it not? EJJ is finding EDataTypeDeserializer well enough but is simply doing so on the wrong element.

I have been digging in on this and the best I can tell the problem has something to do with the cache. I am not sure. Just saying.

In my previous issue, I was asked for the ecore(s) is question. I include them again here. fhir.ecore.zip namespace.ecore.zip xhtml.ecore.zip

martin-fleck-at commented 2 years ago

@threadedblue Hi, I see the problem that you are facing but I am not sure how to properly reproduce it since your metamodels are really big. I agree with you that we expect to see the following deserializations:

<root> [detect object]: EObjectDeserializer
property <telecom> [detect collection with containment]: CollectionDeserializer
  property <telecom.{}> [detect object of type "Telecom"]: EObjectDeserializer
    property <telectom.system> [detect datatype with type enum]: EDataTypeDeserializer
    property <telecom.value> [detect type String]: StringDeserializer
property <resourceType> [detect type String]: StringDeserializer
property <id> [detect type String]: StringDeserializer

We use a few metamodels in our own test cases, see https://github.com/eclipse-emfcloud/emfjson-jackson/tree/master/src/test/resources/model (the one that is rather large is the model.xcore). With these we do test all our individual features such as containment, objects, enums, etc. and as far as I can see nothing seems to be broken, e.g., see https://github.com/eclipse-emfcloud/emfjson-jackson/blob/56fe019f690c208ad22747c1eda48dda4be530f0/src/test/java/org/eclipse/emfcloud/jackson/tests/ReferenceTest.java#L312 for the contained objects deserialization test. Is there any way you could try to provide an example using those test models? It seems to be an unexpected combinations of things that may cause this. If you really believe this is caused by some caching, EObjectFeatureProperty might be at fault here but it is very hard to tell without having a reproducible scenario.

vhemery commented 2 years ago

According to fhir.ecore.zip metamodel, your ContactPoint has a "value" containment feature which is of type "String", and your "String" EClass has a "value" attribute of type StringPrimitive (in addition of eventual "id" and "extension" inherited from "Element"). telecom.value should be a Json object. The same goes for ContactPoint#System, which is a containement reference to "ContactPointSystem" eclass. Your json should rather look like

{
    "telecom": [
      {
        "system": {
                      value : "phone"
                },
        "value": {
                       value : "9786323420"
                }
      }
    ],
    "resourceType": { 
                 "value" : "Organization"
        },
    "id": {
                 "value" : "e44f438a-601b-30fb-85eb-bfaf8ddcb5ad"
        }
}

I have not tested it though, some this might be just an approximation. Also, I'm not sure which type this object is, so there probably should be an eClass attribute there...

If you have difficulties building the json corresponding to your ecore, I suggest you generate the EMF editor from the ecore (see https://www.vogella.com/tutorials/EclipseEMF/article.html ), then create your EMF model with this editor, and finally try and convert this model to Json with Jackson.

If this is not the way you want your json to look, you will have to simplify the Ecore metamodel.

eneufeld commented 1 year ago

Please reopen if the issue still persists.