OndrejKunc / flutter_dynamic_forms

A collection of flutter and dart libraries allowing you to consume complex external forms at runtime.
MIT License
204 stars 60 forks source link

JSON deserialization #19

Closed OndrejKunc closed 5 years ago

OndrejKunc commented 5 years ago

Although I think XML serialized form is easier to read, we should also allow deserialization from some JSON format.

We can even create separate packages, one for XML and one for JSON.

joeblew99 commented 5 years ago

I also would really prefer JSON too :) XML is great, but i code in golang for the backend and support for doing things with JSON is so much higher than XML.

joeblew99 commented 5 years ago

I was looking at the XML and realised that if it was JSON then it would make some sense to use JSONSchema that is part of openAPI. Then i realised that it would mean refactoring quite a bit of Dart code.

SO now i am thinking about writing a OpenAPI to your format converter. I would use this to do it: https://github.com/getkin/kin-openapi It can parse openAPI and then output the JSON that this project uses. It coudl also be extended to do the opposite and take the Dynamic forms JSON data that is returned to the server and convert to openAPI.

Why do this ? Because openAPI and its JSONSchema for validation is used in so many places.

Why am i raising this here ? Just comparing notes as i love this Flutter plugin and to explain how useful JSON support will be.

OndrejKunc commented 5 years ago

The JSON schema converter sounds like a great idea! When we start supporting JSON, it can be potentially very useful for many people.

It coudl also be extended to do the opposite and take the Dynamic forms JSON data that is returned to the server and convert to openAPI.

I am not sure about this part, because right now the idea is to send back to the server only mutable properties, as described here #28 . They can be in a JSON format, but I don't know if the converter is necessary.

OndrejKunc commented 5 years ago

Ok, I have just started implementing the json deserialization and I hit one issue I am not sure how to solve correctly. Imagine we have the following xml:

<?xml version="1.0" encoding="UTF-8"?>
  <container id="form1">
    <label
      id="label1"
      value="John Doe" />
    <label
      id="label2">
      <label.value>
        <expression><![CDATA[
                      "Welcome " + @label1 + "!"
        ]]></expression>
      </label.value>
    </label>
  </container>

I am now thinking how to represent the same components in a JSON. So far I can think of 3 options. Option 1:

{
  "@name": "container",
  "id": "form1",
  "children": [
    {
      "@name": "label",
      "id": "label1",
      "value": "John Doe"
    },
    {
      "@name": "label",
      "id": "label2",
      "value": {
        "expression": "\"Welcome \" + @label1 + \"!\""
      }
    }
  ]
}

Note: the @name key is something i need to identify the type of the component and I don't want to make it collide with another property that's why I put there the @ prefix. Alternatively it can also be something like @type or @typeName.

Option 2:

{
  "name": "container",
  "properties": {
    "id": "form1",
    "children": [
      {
        "name": "label",
        "properties": {
          "id": "label1",
          "value": "John Doe"
        }
      },
      {
        "name": "label",
        "properties": {
          "id": "label2",
          "value": {
            "expression": "\"Welcome \" + @label1 + \"!\""
          }
        }
      }
    ]
  }
}

But this seems too verbose with unnecessary levels of nesting.

Option 3:

{
  "container": {
    "id": "form1",
    "children": [
      {
        "label": {
          "id": "label1",
          "value": "John Doe"
        }
      },
      {
        "label": {
          "id": "label2",
          "value": {
            "expression": "\"Welcome \" + @label1 + \"!\""
          }
        }
      }
    ]
  }
}

There is a similar nesting problem like in the Option 2 and it can be more difficult to parse it.

Right now I would prefer the option 1 but I am open to the discussion before I finish the implementation.

milanjaros commented 5 years ago

Though I would choose the 3rd one, I think you could have implemented all of them ;) (it's opensource, heh?) and the 4th:

{
  "container": {
    "id": "form1",
    "/label": [
      {
        "id": "label1",
        "value": "John Doe"
      },
      {
        "id": "label2",
        "/label.value": {
          "/expression": "
                      \"Welcome \" + @label1 + \"!\"
        "
        }
      }
    ]
  }
}
joeblew99 commented 5 years ago

really cool to see this get picked up.

Options 1, 2 and 3 are fine to me. slightly ugly syntax is not really that important for me. It being robust and easy to program is more important. SO if option 1 is easiest for now, i vote for that one.

We can always refactor it later.

OndrejKunc commented 5 years ago

Thanks for all the feedback. To summarize: