json-editor / json-editor

JSON Schema Based Editor
MIT License
4.43k stars 654 forks source link

Adding object to an array-of-objects includes unwanted object #246

Closed fangq closed 3 years ago

fangq commented 5 years ago

sorry, I am new to JSON schema and json-editor. I have a JSON structure made of an array of objects, see example here

https://github.com/fangq/mcx/blob/72afd6a0bebcca6a83735aa215d07125f1c5bee1/README.txt#L549-L582

the number of objects in the "Shapes" array may vary. I adapted the example from json-editor and try to make an editor for this JSON input, but somehow, creating the Shapes object is not working with json-editor. I suspect that I wrote incorrect schema, but could not find examples how to do this properly.

here is my html editor based on json-editor:

https://github.com/fangq/mcx/blob/etherdome/mcxone/index.html

this schema is what I used for this object is

https://github.com/fangq/mcx/blob/etherdome/mcxone/index.html#L359-L582

I changed oneOf to anyOf, but still have the same issue. Can someone tell me what I did wrong?

thanks

Update Mar 3, 2021

The updated json editor for my schema can be found at

http://tinyurl.com/y9vynjxy

or using the json editor playground link

http://tinyurl.com/ymr9bzhn

the issue is now related to the extra object when adding constructs to the Shapes tab. see updated comments at https://github.com/json-editor/json-editor/issues/246#issuecomment-790189281

schmunk42 commented 5 years ago

Did you take a look at the validation errors, i.e. here

[
  {
    "path": "root.Shapes.0",
    "property": "oneOf",
    "message": "Value must validate against exactly one of the provided schemas. It currently validates against 4 of the schemas."
  },
  {
    "path": "root.Shapes.0.oneOf[4].C0.0",
    "property": "type",
    "message": "Value must be of type number"
  },
  {
    "path": "root.Shapes.0.oneOf[4].C0.1",
    "property": "type",
    "message": "Value must be of type number"
  },
  {
    "path": "root.Shapes.0.oneOf[4].C0.2",
    "property": "type",
    "message": "Value must be of type number"
  },
  {
    "path": "root.Shapes.0.oneOf[4].C1.0",
    "property": "type",
    "message": "Value must be of type number"
  },
  {
    "path": "root.Shapes.0.oneOf[4].C1.1",
    "property": "type",
    "message": "Value must be of type number"
  },
  {
    "path": "root.Shapes.0.oneOf[4].C1.2",
    "property": "type",
    "message": "Value must be of type number"
  },
  {
    "path": "root.Shapes.0.oneOf[5]",
    "property": "type",
    "message": "Value must be of type string"
  }
]

Looks like the oneOf/anyOf selections must be more unique.

fangq commented 5 years ago

@schmunk42, sorry for the long delay. finally have time to look at this again.

I managed to fix the validation errors (by replacing oneOf to anyOf, and a few other minor changes), however, editing the Shapes section is still not yet working.

The now-fixed schema can be found here.

If one click on the "Shapes" tab, and click +row, the Grid object does not seem to be editable. If I switch it to Sphere using the drop down button, and then switch back to Grid, I see the editor panel contains subfields Tag/O/R, which are the sub-fields of Sphere instead of Grid.

If one further choose Box from the dropdown menu, the displayed properties are Tag/Size/Center/R which seems to be merged of Grid and Sphere objects.

I am wondering if there is a problem the way how I defined these sub-item objects, or there is a bug in json editor?

again, the goal is to allow the Shapes section in my json input file to contain 0-many objects of different subfields, as shown in this example input file

https://github.com/fangq/mcx/blob/72afd6a0bebcca6a83735aa215d07125f1c5bee1/README.txt#L549-L582

thanks for your suggestions

schmunk42 commented 5 years ago

If one click on the "Shapes" tab, and click +row, the Grid object does not seem to be editable. If I switch it to Sphere using the drop down button, and then switch back to Grid, I see the editor panel contains subfields Tag/O/R, which are the sub-fields of Sphere instead of Grid.

Could you try setting keep_oneof_values to false.

@pmk65: We don't have this option in the current demo and neither in the new one from you (https://pmk65.github.io/jedemov2/dist/demo.html) - or did I miss something?

Besides that, the behavior looks like a bug to me. It would be great if we could create a simpler test-case reproducing the problem with anyOf CC: @germanbisurgi

fangq commented 5 years ago

hi @schmunk42, thanks for the quick reply. I tried to add the keep_oneof_values:false line in JSONEditor's constructor, but the observation remains the same, except that when I first click on any +row button, it gives me an error Value must be one of the provided types.

A simple reproductor schema can be found below. What I expect to see is to use jsoneditor to add/remove/edit objects into the Shapes[] array construct. The objects (Grid, Sphere, Box, ...) have different titles and required sub-fields. What I see right now is that jsoneditor somehow could not properly list subfields for each selected sub-object, and generates a list of parameters that across multiple objects.

Let me know if you can reproduce this issue, and anything else I can try/provide. thanks again

{
  "title": "Settings",
  "type": "object",
  "required": [
    "Shapes"
  ],
  "format": "categories",
  "properties": {
    "Shapes": {
      "title": "Shapes",
      "type": "array",
      "format": "table",
      "items": {
        "anyOf": [
          {
            "title": "Grid",
            "type": "object",
            "required": [
              "Tag",
              "Size"
            ],
            "items": {
              "properties": {
                "Tag": {
                  "title": "Tag",
                  "type": "integer",
                  "minimum": 0
                },
                "Size": {
                  "title": "Size",
                  "type": "array",
                  "format": "tabs",
                  "items": {
                    "type": "number"
                  },
                  "minItems": 3,
                  "maxItems": 3
                }
              }
            }
          },
          {
            "title": "Sphere",
            "type": "object",
            "required": [
              "Tag",
              "O",
              "R"
            ],
            "properties": {
              "Tag": {
                "title": "Tag",
                "type": "integer",
                "minimum": 0
              },
              "O": {
                "title": "Center",
                "type": "array",
                "format": "tabs",
                "items": {
                  "type": "number"
                },
                "minItems": 3,
                "maxItems": 3
              },
              "R": {
                "title": "Radius",
                "type": "number",
                "minimum": 0
              }
            }
          },
          {
            "title": "Box",
            "type": "object",
            "required": [
              "Tag",
              "O",
              "Size"
            ],
            "properties": {
              "Tag": {
                "title": "Tag",
                "type": "integer",
                "minimum": 0
              },
              "Size": {
                "title": "Size",
                "type": "array",
                "format": "tabs",
                "items": {
                  "type": "number"
                },
                "minItems": 3,
                "maxItems": 3
              },
              "O": {
                "title": "Center",
                "type": "array",
                "format": "tabs",
                "items": {
                  "type": "number"
                },
                "minItems": 3,
                "maxItems": 3
              }
            }
          },
          {
            "title": "Subgrid",
            "type": "object",
            "required": [
              "Tag",
              "O",
              "Size"
            ],
            "properties": {
              "Tag": {
                "title": "Tag",
                "type": "integer",
                "minimum": 0
              },
              "Size": {
                "title": "Size",
                "type": "array",
                "format": "tabs",
                "items": {
                  "type": "number"
                },
                "minItems": 3,
                "maxItems": 3
              },
              "O": {
                "title": "Center",
                "type": "array",
                "format": "tabs",
                "items": {
                  "type": "number"
                },
                "minItems": 3,
                "maxItems": 3
              }
            }
          },
          {
            "title": "Cylinder",
            "type": "object",
            "required": [
              "Tag",
              "C0",
              "C1",
              "R"
            ],
            "properties": {
              "Tag": {
                "title": "Tag",
                "type": "integer",
                "minimum": 0
              },
              "C0": {
                "title": "Size",
                "type": "array",
                "format": "tabs",
                "items": {
                  "type": "number"
                },
                "minItems": 3,
                "maxItems": 3
              },
              "C1": {
                "title": "Center",
                "type": "array",
                "format": "tabs",
                "items": {
                  "type": "number"
                },
                "minItems": 3,
                "maxItems": 3
              },
              "R": {
                "title": "Radius",
                "type": "number",
                "minimum": 0
              }
            }
          },
          {
            "title": "Name",
            "type": "string"
          }
        ]
      }
    }
  }
}
pmk65 commented 5 years ago

@pmk65: We don't have this option in the current demo and neither in the new one from you (https://pmk65.github.io/jedemov2/dist/demo.html) - or did I miss something?

You are correct. I must have missed that one. It's now available at the Playground page.

schmunk42 commented 5 years ago

Nice!

So I think, at least the switching works better with this option, but there's still an issue with initialization of anyOf and I think also oneOf items.

[edit]

Thinking more about it... it's actually OK to actively select the type you want, but you can not select the first item, because it is already selected. How about adding an empty item (or "please select a type") at the top?

fangq commented 3 years ago

I would like to give an update to this issue - I figured out how to properly define json-schema to for arrays of objects, such as examples shown here:

https://github.com/fangq/mcx/blob/72afd6a0bebcca6a83735aa215d07125f1c5bee1/README.txt#L549-L582

with the updated json schema, I was able to get valid inputs using either json editor's default interface,

http://tinyurl.com/y9vynjxy

or using the json editor playground link

http://tinyurl.com/ymr9bzhn

however, I found one issue (which sort persisted from previous observations) - if you click on the "Shapes" tab, click "+row", if you select any object other than "Grid", for example, "Sphere", you will see an extra "Grid" object attached at the bottom of the desired object. A screenshot is attached.

mcx_json_editor_bug

Currently, json editor outputs this JSON construct "Shapes":[{"Sphere":{...}, "Grid": {...}}] but the desired output is "Shapes":[{"Sphere":{...} }]

or, if multiple objects shall be included, I need "Shapes":[ {"Grid": {...}}, {"Sphere":{...}} ]

so that I can have multiple spheres or grids etc.

in your opinion, is this a bug in my json schema definition, or json editor? my schema is defined here

https://github.com/fangq/mcx/blob/master/schema/mcxinput.json

schmunk42 commented 3 years ago

Pretty complex schema :)

I do not really understand the problem, eg. with desired output. there's just a additional closing bracket } Same for multiple options.

Could you create a small schema which reproduces the problem with "Shapes"?

pmadril commented 3 years ago

@fangq If you set the global "No additional object properties" option or use "additionalProperties": false in each "anyOf" alternative, you solve your problem. I went through this some time ago.

A simple schema showing the problem:

{
  "title": "Settings",
  "type": "object",
  "required": [
    "Shapes"
  ],
  "properties": {
    "Shapes": {
      "title": "Shapes",
      "type": "array",
      "format": "table",
      "items": {
        "anyOf": [
          {
            "title": "Grid",
            "type": "object",
            "required": [
              "Grid"
            ],
            "properties": {
              "Grid": {
                "title": "Grid",
                "type": "object",
                "required": [
                  "Tag"
                ],
                "properties": {
                  "Tag": {
                    "title": "Tag",
                    "type": "integer",
                    "minimum": 0
                  }
                }
              }
            }
          },
          {
            "title": "Sphere",
            "type": "object",
            "required": [
              "Sphere"
            ],
            "properties": {
              "Sphere": {
                "title": "Sphere",
                "type": "object",
                "required": [
                  "R"
                ],
                "properties": {
                  "R": {
                    "title": "Radius",
                    "type": "number",
                    "minimum": 0
                  }
                }
              }
            }
          },
          {
            "title": "Box",
            "type": "object",
            "required": [
              "Box"
            ],
            "properties": {
              "Box": {
                "title": "Box",
                "type": "object",
                "required": [
                  "Tag"
                ],
                "properties": {
                  "Tag": {
                    "title": "Tag",
                    "type": "integer",
                    "minimum": 0
                  }
                }
              }
            }
          }
        ]
      }
    }
  }
}

Same schema, solving the problem with "additionalProperties": false:

{
  "title": "Settings",
  "type": "object",
  "required": [
    "Shapes"
  ],
  "properties": {
    "Shapes": {
      "title": "Shapes",
      "type": "array",
      "format": "table",
      "items": {
        "anyOf": [
          {
            "title": "Grid",
            "type": "object",
            "additionalProperties": false,
            "required": [
              "Grid"
            ],
            "properties": {
              "Grid": {
                "title": "Grid",
                "type": "object",
                "required": [
                  "Tag"
                ],
                "properties": {
                  "Tag": {
                    "title": "Tag",
                    "type": "integer",
                    "minimum": 0
                  }
                }
              }
            }
          },
          {
            "title": "Sphere",
            "additionalProperties": false,
            "type": "object",
            "required": [
              "Sphere"
            ],
            "properties": {
              "Sphere": {
                "title": "Sphere",
                "type": "object",
                "required": [
                  "R"
                ],
                "properties": {
                  "R": {
                    "title": "Radius",
                    "type": "number",
                    "minimum": 0
                  }
                }
              }
            }
          },
          {
            "title": "Box",
            "additionalProperties": false,
            "type": "object",
            "required": [
              "Box"
            ],
            "properties": {
              "Box": {
                "title": "Box",
                "type": "object",
                "required": [
                  "Tag"
                ],
                "properties": {
                  "Tag": {
                    "title": "Tag",
                    "type": "integer",
                    "minimum": 0
                  }
                }
              }
            }
          }
        ]
      }
    }
  }
}

I think we have a real problem here, but I don't have time to dig it up. As far as I remember, there is an array of objects that must be cleaned of dangling references. The phantom "Grid" object that appears is not a real "Grid" object because the type of properties is not defined. So the UI shows a type selector, beside the property title, for all the phantom "Grid" properties. It's the same thing as dynamic adding a new property. Also, after selecting "Sphere", the Shapes Properties button, shows "Grid" phantom as an optional property and "Sphere" as required.

May be this helps.

fangq commented 3 years ago

thank you @pmadril , the "No additional object properties" option indeed solved the problem! thank you very much. I will leave this ticket open so you can use it to track this issues down in the future. thanks again!