改变 JSON 以使用 react-jsonschema-form

Mutating JSON to work with react-jsonschema-form

我开始使用 react-jsonschema-form,它需要以特定格式输入。 我得到了一个嵌套的 JSON,但我无法根据所需的输入格式递归地改变 JSON。

给出的是这个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"
  }
}

而这个新的JSON需要递归生成

{
  "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"
      }
    }
  }
}

我可以使用迭代格式实现此目的,但这是不可扩展的。为了用递归方法得到这个,我已经被困了几个小时。

如果我能得到一种递归方法来将给定的 JSON 更新为 javascript 中所需的格式,我将不胜感激。

我想这就完成了。如果您看到我遗漏的内容,请告诉我。

// 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" />

JSON.parse reviver parameter可以用来转换值:

var 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"
  }
}`

var obj = JSON.parse(json, (key, val, type = typeof val) => !key ? val : 
  { type, title: key, [type === 'object' ? 'properties' : 'default']: val } )
  
console.log(obj)