在React.js中如何获取JSON对象的键和值

3

我是新手,正在尝试在我的网页中实现JSON对象的所有键和值。我有以下JSON结构。我希望所有的键和值都被打印在我的网页上,其中键应该被打印为标签。

{
    "key1": "value1",
    "key2": "value2",
    "key3": "value3",
    "key4":{
       "k1": "val1",
        "k2": {
        "p1": "v1",
        "p2": "v2",
        "p3": "v3"
            }
          }
        }

我已经编写了以下代码来获取此JSON的键和值。
getValues() {
        let arr = [];
        arr = Object.keys(this.props.myArr).map(key =>
            <div key={this.props.data[key]} className="row">
                <div className="col-xs-6">{key}</div>
                <div className="col-xs-6">{this.props.myArr[key]}
                </div>
            </div>

        )
        return arr;
    }
render() {
    return (
        <div>
            <Header />
            <div className="content">
                {this.getValues()}
            </div>
        </div>
    )
}

}

props.myArr包含整个对象。

我能够打印键和值,但无法打印key4(p1,p2,p3)下的嵌套对象。我希望所有的键和它们的值都能依次打印在我的网页上。请问我做错了什么,如何访问JSON对象的所有键(作为标签)和值。

编辑 -

const myObj = {
  "key1": "value1",
  "key2": "value2",
  "key3": "value3",
  "key4": {
    "k1": "val1",
    "k2": {
      "p1": "v1",
      "p2": "v2",
      "p3": "v3"
    }
  }
}


class Details extends React.component{
constructor(){
  this.getValues = this.getValues.bind(this);
}
getValues() {
        let arr = [];
        arr = Object.keys(myObj).map(key =>
            <div key={myObj[key]} className="row">
                <div className="col-xs-6">{key}</div>
                <div className="col-xs-6">{myObj[key]}
                </div>
            </div>

        )
        return arr;
    }

generateData(myObj) {

        const newData = Object.keys(myObj).reduce((result, currentKey) => {
          if (typeof myObj[currentKey] === 'string' || myObj[currentKey] instanceof String) {
            const elementToPush = getValues(currentKey, myObj[currentKey]);
            result.push(elementToPush);
          } else {
            const nested = generateData(myObj[currentKey]);
            result.push(...nested);
          }
          return result;
        }, []);
        return newData;
      }

render() {
    return (
        <div>
            <Header />
            <div className="content">
                {this.generateData(myObj)}
            </div>
        </div>
    )
}
}

我正在使用map函数的getValues方法来检索第一层键和值,因为您在generateElement()下提供的语法会导致错误。


如果您想显示更深层嵌套的数据,那么您不能简单地映射JSON第一层的键。您想如何显示“key4”中的数据? - feihcsim
你想要递归 - Felix Kling
1个回答

6
你需要使用递归。不过,你的设计中缺少一个重要的条件:程序应该在何时提取值。例如,我们定义如果给定“key”的“value”是字符串,那么就将其呈现在页面上。这个条件看起来会像这样:
if (typeof data[key] === 'string' || data[key] instanceof String)

然后,有了这个决定,您可以编写一个函数,该函数将接受一个数据对象并递归地遍历对象的键。基于上述条件,它将返回value或对具有value作为新数据对象的同一函数的另一个调用。
该函数的代码块如下所示:
function generateData(data) {
  const newData = Object.keys(data).reduce((result, currentKey) => {
    if (typeof data[currentKey] === 'string' || data[currentKey] instanceof String) {
      result.push(currentKey);
    } else {
      const nested = generateData(data[currentKey]);
      result.push(...nested);
    }
    return result;
  }, []);
  return newData;
}

我在这里使用 .reduce 来构建一个新的数组。正如上面提到的,根据上述条件,我将向新数组中添加key或者以value作为新数据对象进行递归调用此函数并返回的结果。
请注意,递归调用会返回一个数组,因此我使用展开语法来提取它的元素。

现在,我们希望将keyvalue呈现到DOM上。
因此,我们不仅要推入keyvalue,而是要推入一个元素。

以下是一个完整的运行示例:

const myData = {
  "key1": "value1",
  "key2": "value2",
  "key3": "value3",
  "key4": {
    "k1": "val1",
    "k2": {
      "p1": "v1",
      "p2": "v2",
      "p3": "v3"
    }
  }
}

const generateElement = (key,value) => {
  return (
    <div key={key} className="row">
      <div className="col-xs-6 ins-label">{key}</div>
      <div className="col-xs-6">{value}</div>
    </div>
  );
}

function generateData(data) {
  const newData = Object.keys(data).reduce((result, currentKey) => {
    if (typeof data[currentKey] === 'string' || data[currentKey] instanceof String) {
      const elementToPush = generateElement(currentKey, data[currentKey]);
      result.push(elementToPush);
    } else {
      const nested = generateData(data[currentKey]);
      result.push(...nested);
    }
    return result;
  }, []);
  return newData;
}

class App extends React.Component {
  render() {
  const { data } = this.props;
    return (
      <div>
        {generateData(data)}        
      </div>
    )
  }
}

ReactDOM.render(<App data={myData} />, document.getElementById('root'));
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>


我在generateData中使用了Object.keys。而且我选择使用.reduce而不是.map - Sagiv b.g
是的,只要您保持对象的这种形式。我的意思是,key 可以是 StringObject。请注意,我们在条件中不检查 Array - Sagiv b.g
你需要将它传递给 generateData,然后 generateData 将使用相关的 keyvalue对调用 generateElement - Sagiv b.g
我已经更新了我的更改。现在我遇到的错误是getValues()未定义。 - user2138675
这个可以工作,但是现在我看到一个错误,即对象不是React的有效子元素(发现具有键{k1,k2}的对象)。如果你想渲染一组子元素,请使用数组。 - user2138675
显示剩余12条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接