如何在React Native中解析JSON数据

时间:2018-12-14 09:56:45

标签: json reactjs react-native

嗨,我是React本机开发的新手,如何解析以下数据请帮助我

这是我的代码

componentDidMount() {
fetch('https://api.myjson.com/bins/96ebw')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.Pharmacy,
}, 

);
})
.catch((error) => {
console.error(error);
});
}

renderItem(dataSource) {
const { List: list } = this.state.dataSource
const { item } = dataSource;

return (
<View style={styles.itemBlock}>
<View style={styles.itemMeta}>
<Text style={styles.itemName}>{item.RxDrugName}</Text>
<Text style={styles.itemLastMessage}>{item.RxNumber}</Text>
</View>

<View style={styles.footerStyle}>
<View style={{ paddingVertical: 10 }}>
<Text style={styles.status}>{ item.StoreNumber }</Text>
</View>

<View style={{ justifyContent: 'center', alignItems: 'center' }}>
<Image source={require('../assets/right_arrow_blue.png')} />
</View>

</View>
</View>
);
}

json是

[
  {
    "Pharmacy": {
      "Name": "Hillcrest MOB Pharmacy",
      "StoreNumber": "254",
      "Address": {
        "StreetAddress": "50 Hillcrest Medical Blvd Ste 200-1",
        "City": "WACO",
        "State": "TX",
        "Zip": "76712"
      },
      "IsDefault": false
    },
    "ReadyForPickups": [
      {
        "RxDrugName": "Tizanidine HCL 4mg Caps",
        "RxNumber": "6000295",
        "StoreNumber": "254",
        "PatientPay": "15.59"
      }
    ]
  },

  {
    "Pharmacy": {
      "Name": "Waco Pharmacy",
      "StoreNumber": "251",
      "Address": {
        "StreetAddress": "1412 N Valley Mills, Suite 116",
        "City": "WACO",
        "State": "TX",
        "Zip": "76710"
      },
      "IsDefault": false
    },
    "ReadyForPickups": [
      {
        "RxDrugName": "Fluoxetine HCL 40mg Caps",
        "RxNumber": "6000233",
        "StoreNumber": "251",
        "PatientPay": "17.3"
      }
    ]
  }

]

2 个答案:

答案 0 :(得分:2)

问题在于json响应是对象数组。您需要从数组中选择对象。

例如,如果您想要数组中的第一项,则可以执行以下操作

const first = jsonResponse[0]

{
  "Pharmacy":{
    "Name":"Hillcrest MOB Pharmacy",
    "StoreNumber":"254",
    "Address":{
      "StreetAddress":"50 Hillcrest Medical Blvd Ste 200-1",
      "City":"WACO",
      "State":"TX",
      "Zip":"76712"
    },
    "IsDefault":false
  },
  "ReadyForPickups":[
    {
      "RxDrugName":"Tizanidine HCL 4mg Caps",
      "RxNumber":"6000295",
      "StoreNumber":"254",
      "PatientPay":"15.59"
    }
  ]
}

现在,您可以尝试使用first.Pharmacy从那里捕获数据。

因此console.log(first.Pharmacy.Name)应该给您Hillcrest MOB药房

您似乎也正在尝试创建并显示这些药房的列表。根据您拥有的物品数量,有两种方法可以做到这一点。但是,最有效和最简单的方法是使用FlatList。如果出于某种原因它延伸到页面之外,则将负责该视图。

所以让我们设置FlatList。

首先,从react-native导入FlatList

第二次将componentDidMount中的setState调用更改为

this.setState({
  isLoading: false,
  dataSource: responseJson
}

添加以下方法

renderItem = ({item, index}) => {
  let { Pharmacy, ReadyForPickups } = item;

  if(!ReadyForPickups[0]) return null;
  let details = ReadyForPickups[0]

  return (
  <View style={styles.itemBlock}>
    <View style={styles.itemMeta}>
      <Text style={styles.itemName}>{details.RxDrugName}</Text>
      <Text style={styles.itemLastMessage}>{details.RxNumber}</Text>
    </View>

    <View style={styles.footerStyle}>
      <View style={{ paddingVertical: 10 }}>
        <Text style={styles.status}>{ details.StoreNumber }</Text>
      </View>

      <View style={{ justifyContent: 'center', alignItems: 'center' }}>
        <Image source={require('../assets/right_arrow_blue.png')} />
      </View>

    </View>
  </View>
  );
}

keyExtractor = (item, index) => {
  return index.toString();
}

然后您的render方法应该看起来像这样

  render () {
      return (
        <View style={{flex: 1}}>
          <FlatList
            data={this.state.dataSource}
            keyExtractor={this.keyExtractor}
            renderItem={this.renderItem}
          />
        </View>
      );
    }

然后它应该看起来像这样。显然样式丢失了,我使用了替代图像。但这应该是您要寻找的想法。

enter image description here

希望这足以获取所需的数据。

更新

这是一个完全正常工作的组件,它呈现与上面类似的列表

import React, { Component } from 'react';
import { View, Text, FlatList, Image } from 'react-native';
import PropTypes from 'prop-types';

// import screens styles
import styles from './styles';

class Pharmacy extends Component {
  /**
   * Construct component class
   * @param {object} props
   */
  constructor (props: {}) {
    super(props);

    this.state = {
        isLoading: false,
        dataSource: responseJson
    };
  }

  componentDidMount () {
    fetch('https://api.myjson.com/bins/96ebw')
      .then((response) => response.json())
      .then((responseJson) => {
        this.setState({
          isLoading: false,
          dataSource:[]
        });
      });
  }

  renderItem = ({item, index}) => {
    let { Pharmacy, ReadyForPickups } = item;

    if (!ReadyForPickups[0]) return null;
    let details = ReadyForPickups[0];

    return (
      <View style={styles.itemBlock}>
        <View style={styles.itemMeta}>
          <Text style={styles.itemName}>{details.RxDrugName}</Text>
          <Text style={styles.itemLastMessage}>{details.RxNumber}</Text>
        </View>

        <View style={styles.footerStyle}>
          <View style={{ paddingVertical: 10 }}>
            <Text style={styles.status}>{ details.StoreNumber }</Text>
          </View>

          <View style={{ justifyContent: 'center', alignItems: 'center' }}>
            <Image source={{uri: 'https://images.pexels.com/photos/949586/pexels-photo-949586.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500'}}
              style={{height: 50, width: 50}}/>
          </View>

        </View>
      </View>
    );
  }

  keyExtractor = (item, index) => {
    return index.toString();
  }

  render () {
    return (
      <View style={{flex: 1}}>
        <FlatList
          data={this.state.dataSource}
          keyExtractor={this.keyExtractor}
          renderItem={this.renderItem}
        />
      </View>
    );
  }
}

export default Pharmacy;

更新2

在与原始问题发布者聊天之后,他们似乎只希望将ReadyForPickups项显示为单个列表。

这可以通过执行映射和减少responseJson来完成,以便将setState调用更新为以下内容

this.setState({
  isloading: false,
  dataSource: responseJson.map(item => item.ReadyForPickups).reduce((acc, currValue) => { return acc.concat(currValue); }, [])
});

这会将ReadyForPickup项目分组为一个长列表,如下所示:

[
  {
    "RxDrugName":"Tizanidine HCL 4mg Caps",
    "RxNumber":"6000295",
    "StoreNumber":"254",
    "PatientPay":"15.59"
  },
  {
    "RxDrugName":"Hydroxychloroquine Sulfate 200 Tabs",
    "RxNumber":"6000339",
    "StoreNumber":"201",
    "PatientPay":"16.18"
  },
  {
    "RxDrugName":"Naratriptan HCL 2.5mg Tabs",
    "RxNumber":"6000300",
    "StoreNumber":"111",
    "PatientPay":"39.04"
  },
  {
    "RxDrugName":"Tizanidine HCL 4mg Caps",
    "RxNumber":"6000457",
    "StoreNumber":"08",
    "PatientPay":"15.59"
  },
  {
    "RxDrugName":"Lisinopril 20mg Tabs",
    "RxNumber":"6000318",
    "StoreNumber":"08",
    "PatientPay":"13.46"
  },
  {
    "RxDrugName":"Fluoxetine HCL 40mg Caps",
    "RxNumber":"6000233",
    "StoreNumber":"251",
    "PatientPay":"17.3"
  },
  {
    "RxDrugName":"Tizanidine HCL 4mg Caps",
    "RxNumber":"6000222",
    "StoreNumber":"232",
    "PatientPay":"15.59"
  },
  {
    "RxDrugName":"Memantine HCL 5mg Tabs",
    "RxNumber":"6000212",
    "StoreNumber":"231",
    "PatientPay":"17.99"
  },
  {
    "RxDrugName":"Clonidine HCL 0.1mg Tabs",
    "RxNumber":"6000339",
    "StoreNumber":"07",
    "PatientPay":"12.71"
  },
  {
    "RxDrugName":"Benazepril HCL 5mg Tabs",
    "RxNumber":"6000261",
    "StoreNumber":"06",
    "PatientPay":"13.45"
  },
  {
    "RxDrugName":"Clonidine HCL 0.1mg Tabs",
    "RxNumber":"6000524",
    "StoreNumber":"02",
    "PatientPay":"12.73"
  },
  {
    "RxDrugName":"Timolol Maleate 20mg Tabs",
    "RxNumber":"6000771",
    "StoreNumber":"02",
    "PatientPay":"15.33"
  },
  {
    "RxDrugName":"Benazepril HCL 5mg Tabs",
    "RxNumber":"6002370",
    "StoreNumber":"01",
    "PatientPay":"13.45"
  },
  {
    "RxDrugName":"Eliquis 5mg Tabs",
    "RxNumber":"6002609",
    "StoreNumber":"01",
    "PatientPay":"20.88"
  },
  {
    "RxDrugName":"Atorvastatin Calcium 20mg Tabs",
    "RxNumber":"6002602",
    "StoreNumber":"01",
    "PatientPay":"17.69"
  },
  {
    "RxDrugName    ":"Astagraf Xl 0.5mg Cp24",
    "RxNumber":"6000232",
    "StoreNumber":"278",
    "PatientPay":"15.33"
  },
  {
    "RxDrugName":"Ropinirole HCL 0.5mg Tabs",
    "RxNumber":"6000067",
    "StoreNumber":"112",
    "PatientPay":"14.75"
  },
  {
    "RxDrugName":"Ciprofloxacin HCL 0.3% Soln",
    "RxNumber":"6000217",
    "StoreNumber":"275",
    "PatientPay":"55.06"
  },
  {
    "RxDrugName":"Sotalol HCL 240mg Tabs",
    "RxNumber":"6000575",
    "StoreNumber":"09",
    "PatientPay":"17.5"
  }
]

要匹配新的数据源,应更新renderItem函数,以便显示列表。

renderItem = ({item, index}) => {

  return (
  <View style={styles.itemBlock}>
    <View style={styles.itemMeta}>
      <Text style={styles.itemName}>{item.RxDrugName}</Text>
      <Text style={styles.itemLastMessage}>{item.RxNumber}</Text>
    </View>

    <View style={styles.footerStyle}>
      <View style={{ paddingVertical: 10 }}>
        <Text style={styles.status}>{item.StoreNumber }</Text>
      </View>

      <View style={{ justifyContent: 'center', alignItems: 'center' }}>
        <Image source={require('../assets/right_arrow_blue.png')} />
      </View>

    </View>
  </View>
  );
}

答案 1 :(得分:1)

您的responseJson是JSON对象的数组,格式为:

{
    "Pharmacy": {
      "Name": "Hillcrest MOB Pharmacy",
      "StoreNumber": "254",
      "Address": {
        "StreetAddress": "50 Hillcrest Medical Blvd Ste 200-1",
        "City": "WACO",
        "State": "TX",
        "Zip": "76712"
      },
      "IsDefault": false
    },
    "ReadyForPickups": [
      {
        "RxDrugName": "Tizanidine HCL 4mg Caps",
        "RxNumber": "6000295",
        "StoreNumber": "254",
        "PatientPay": "15.59"
      }
    ]
}

所以你应该

.then((responseJson) => {
    this.setState({
       isLoading: false,
       dataSource: responseJson
    }
);

render()中,您可以map() dataSource中的每个项目,并以您的代码调用renderItem()

render() {
  return (
     <View>
       {this.state.dataSource.map(item => this.renderItem(item))}
     </View>
  )
}

renderItem(item)中,item现在是具有上述格式的JSON对象,您可以轻松呈现它。

renderItem(obj) {

   const item = (obj.ReadyForPickups || [])[0] || {};
   // this will secure your app not crash when item is invalid data.

   return (
     <View style={styles.itemBlock}>
       <View style={styles.itemMeta}>
         <Text style={styles.itemName}>{item.RxDrugName}</Text>
         <Text style={styles.itemLastMessage}>{item.RxNumber}</Text>
       </View>

       <View style={styles.footerStyle}>
         <View style={{ paddingVertical: 10 }}>
           <Text style={styles.status}>{ item.StoreNumber }</Text>
         </View>

         <View style={{ justifyContent: 'center', alignItems: 'center' }}>
           <Image source={require('../assets/right_arrow_blue.png')} />
         </View>

       </View>
   </View>
);
}