Search code examples
javascriptjsonobjectreact-jsonschema-forms

Mutating JSON to work with react-jsonschema-form


I am getting started with react-jsonschema-form, It requires input in a particular format. I am given a nested JSON but i am unable to recursively mutate the JSON according to the required input format.

Given is this JSON

{
  "Coordinates": {
    "X-Coordinate": 47,
    "Y-Coordinate": -122
  },
  "Coordination Type": {
    "Cartesion Mode": false,
    "Starting Range": {
      "Start": 8000,
      "End": 9000
    }
  },
  "Map": {
    "Offline Map": false,
    "URL": "http://localhost:9000"
  }
}

And this new JSON is needed to be generated recursively.

{
  "Coordinates": {
    "type": "object",
    "title": "Coordinates",
    "properties": {
      "X-Coordinate": {
        "type": "number",
        "title": "X-Coordinate",
        "default": 47
      },
      "Y-Coordinate": {
        "type": "number",
        "title": "Y-Coordinate",
        "default": -122
      }
    }
  },
  "Coordination Type": {
    "type": "object",
    "title": "Coordination Type",
    "properties": {
      "Cartesion Mode": {
        "type": "boolean",
        "title": "Cartesion Mode",
        "default": false
      },
      "Starting Range": {
        "type": "object",
        "title": "Start Range",
        "properties": {
          "Start": {
            "type": "number",
            "title": "Start",
            "default": 8000
          },
          "End": {
            "type": "number",
            "title": "End",
            "default": 9000
          }
        }
      }
    }
  },
  "Map": {
    "type": "object",
    "title": "Map",
    "properties": {
      "Offline Map": {
        "type": "boolean",
        "title": "Offline Map",
        "default": false
      },
      "URL": {
        "type": "string",
        "title": "URL",
        "default": "http://localhost:9000"
      }
    }
  }
}

I am able to achieve this using iterative format but that is not scalable. And i have been stuck for hours to get this in recursive method.

I would really appreciate if i get a recursive method to update this given JSON to the required format in javascript.


Solution

  • I think this gets it done. Let me know if you see something I missed.

    // input data copied from question
    const input = {
      "Coordinates": {
        "X-Coordinate": 47,
        "Y-Coordinate": -122
      },
      "Coordination Type": {
        "Cartesion Mode": false,
        "Starting Range": {
          "Start": 8000,
          "End": 9000
        }
      },
      "Map": {
        "Offline Map": false,
        "URL": "http://localhost:9000"
      }
    };
    
    // recursive field conversion function
    const convertField = (key, value) => (
      {
        type: typeof value, // 'object', 'boolean', 'number', 'string'
        title: key, // field name is also the title (e.g. 'Starting Range')
        ...(
          typeof value !== 'object'
          ? { default: value } // primitive type. default and we're done
          : {  
            properties: Object.entries(value)
            .reduce((facc, [field, fvalue]) => ({
              ...facc, // keep previous iterations
              [field]: { // keep the field name, e.g. 'Starting Range',
              ...convertField(field, fvalue) // recurse for the field's value
            }
          }), {})
        }
        )
      }
      );
      
      // kick it off
      const output = Object.entries(input)
      .reduce((acc, [key, value]) => ({
        ...acc, // retain previous iteration results
        [key]: {...convertField(key, value)} // convert each property
      }), {}
      );
      
      // show the results
      document.getElementById('result').innerText = (JSON.stringify(output, null, 2))
      
    <pre id="result" />