AykutSarac / jsoncrack.com

✨ Innovative and open-source visualization application that transforms various data formats, such as JSON, YAML, XML, CSV and more, into interactive graphs.
https://jsoncrack.com/
Other
30.49k stars 1.89k forks source link

[Bug] Nested objects causing empty nodes #27

Closed AykutSarac closed 1 year ago

AykutSarac commented 2 years ago

Issue

Empty nodes occurs in situations similar to nested objects.

Reproduction

Following data could be addressed regarding this: https://raw.githubusercontent.com/json-schema-org/json-schema-spec/draft-next/schema.json

20220428_231517

Expected behaviour

Edges should be connected to parent instead.

noobyogi0010 commented 2 years ago

Hey @AykutSarac I would love to work on this issue, if no one else has taken it up. Thanks!

AykutSarac commented 2 years ago

Hey @AykutSarac I would love to work on this issue, if no one else has taken it up. Thanks!

I appreciate it so much, the problem is likely to be caused by the algorithm at src/utils/json-editor-parser.ts

noobyogi0010 commented 2 years ago

Okay, I will have a look at it. Thank you!

bjbrewster commented 2 years ago

Is the empty node where the object properties that are not arrays or objects is shown?

AykutSarac commented 2 years ago

Is the empty node where the object properties that are not arrays or objects is shown?

Following data is a good example of what's wrong when pasted to jsonvisio.com:

{
  "properties": {
    "definitions": {
      "type": "object",
      "additionalProperties": {
        "$dynamicRef": "#meta"
      },
      "deprecated": true
    }
  }
}
faizanu94 commented 2 years ago

Connecting edges to parent would not be visually suitable if there are siblings of the empty node, I've raised a pull request for this issue which handles this scenario as follows: jsonvisio com (Wed Jun 08 2022)

noobyogi0010 commented 2 years ago

@AykutSarac is there any progress on this issue? Was someone able to find the root cause for this issue? Thanks

AykutSarac commented 2 years ago

@AykutSarac is there any progress on this issue? Was someone able to find the root cause for this issue? Thanks

@noobyogi0010 The root issue is mainly because of the issue mentioned here: https://github.com/AykutSarac/jsonvisio.com/issues/51

The issue here is a node hides keys with values of Array or Objects to create seperate nodes, then the node displays single value keys such as bool, string or other kinds. When there is no other type like a number or string it becomes an empty node. If the issue I mentioned above gets resolved this will be solved mainly.

Empty nodes could be handled as a next step after #51 gets resolved. I appreciate any sort of help.

noobyogi0010 commented 2 years ago

@AykutSarac Okay. I'll try to fix #51 first then. Thanks

KarlHeitmann commented 2 years ago

I think the problem here is that the code is doing what it should do. Take a look at the file jsonParser.ts, inside it, every time you have a nested object, you convert it into something similar to an array to generate the children. That's the reason why using this example:

{
  "properties": {
    "definitions": {
      "type": "object",
      "additionalProperties": {
        "$dynamicRef": "#meta"
      },
      "deprecated": true
    }
  }
}

You've got on the second node the word properties in orange. Take a look at this ArrayOrNestedObject? key, can you tell what type of value is associated to the key? judging only by what you see on the graph?

jsoncrack1

You can't tell if the associated value is either a nested object or an array of only one element. It is impossible, because on the transformation process, when you are generating the data structure that is going to be used later on to render edges and nodes, when you find a nested object, you turn it into an array, so that later on you can apply your function recursively to it's children. The problem is your nested objects are treated as an array, so some weird things will happen. Like this empty node with array subnodes.

image

Here is the code & complete screenshot

image

{
  "squadName": "Super hero squad",
  "homeTown": "Metro City",
  "formed": 2016,
  "secretBase": "Super tower",
  "ArrayOrNestedObject?": {
    "name": "Molecule Man",
    "age": 29,
    "secretIdentity": "Dan Jukes",
    "powers": [
      "Radiation resistance",
      "Turning tiny",
      "Radiation blast"
    ]
  },
  "active": true,
  "members": [
    {
      "name": "Molecule Man",
      "age": 29,
      "secretIdentity": "Dan Jukes",
      "powers": [
        "Radiation resistance",
        "Turning tiny",
        "Radiation blast"
      ]
    }
  ]
}

I think to solve this issue, one must answer the question: How do I want to represent a nested object? Then, build a function that detects nested objects inside a JSON, and apply that function that will render something visually different from a nested array. Something clearly different.

I like fractals, and I think whenever you have something nested in code, there is a fractal here. Eg, folders and files, you can apply the same function that renders the root folder to a nested folder, and it will render the file system nested. Each time you detect a folder, you can apply the same function that renders the original root folder.

Take a look at "ArrayOrNestedObject" key here:

image

Can you see the "{}" string associated to the key? Imagine ArrayOrNestedObject has a nested object as associated value. JsonCrack will render the nested object as "{}", bue when you hover it with the mouse, you will get the hand with the finger (telling you to click it), and when you click it, the same function that renders the whole JSON is applied to the nested object, and will render a new canvas showing you the content of the nested object, and if there is a sub-sub-nested-object, it will be rendered again as "{}" and you can click it to view it's contents. Like a russian doll, like a fractal.

This approach is what I applied here With this approach, it is very simple to build any function to handle the data you are working on. Here is an example of a function that searches a subtree with an id passed as argument. This approach will not need to create a new fancy node to show. After all, this is what in reality is a nested object inside a JSON: it is a full data structure stored inside and nested in the object, in the other hand, an array is a pointer (an arrow ) signaling a set of elements.

KarlHeitmann commented 2 years ago

FRACTALS! Here is mandelbrot fractal, and what you have in a nested object, the same function is applied in the big things, and in the little things with complex outcomes.

mandelbrot-zoom-fractal