如何在本机反应中解析json数据

Posted

技术标签:

【中文标题】如何在本机反应中解析json数据【英文标题】:How to parse json data in react native 【发布时间】:2019-05-15 14:01:07 【问题描述】:

您好,我是 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"
      
    ]
  

]

【问题讨论】:

React Native 中不需要解析数据,可以直接访问对象,如response[0].Pharmacy.name @rutvik-bhatt 如果您不介意,请用 for 循环添加答案,我没听清楚 【参考方案1】:

问题在于 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 Pharmacy

您似乎也在尝试创建和显示这些药房的列表。根据您拥有的项目数量,有几种方法可以做到这一点。然而,最高效和最简单的是使用 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 () 
      return (
        <View style=flex: 1>
          <FlatList
            data=this.state.dataSource
            keyExtractor=this.keyExtractor
            renderItem=this.renderItem
          />
        </View>
      );
    

那么它应该看起来像这样。显然缺少样式,我使用了替代图像。但这应该是您正在寻找的想法。

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

更新

这是一个完整工作的组件,它呈现一个类似于上面的列表

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: true,
        dataSource: []
    ;
  

  componentDidMount () 
    fetch('https://api.myjson.com/bins/96ebw')
      .then((response) => response.json())
      .then((responseJson) => 
        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=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 执行 map 和 reduce 来完成,因此 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>
  );

【讨论】:

我想获取所有 rxdrugnames ,请您帮忙 @UmaAchanta 我已经更新了我的答案,以展示如何在 FlatList 中使用这些数据。获取 RxDrugName 时需要小心,因为 ReadyForPickups 是一个对象数组,你永远不知道它是否为空。 @UmaAchanta,一切顺利吗? @UmaAchanta 我刚刚编辑了我的帖子,以便有一个完整的工作组件。您只需要创建一个样式文件。因为没有你的图片,所以我更改了图片 uri。 这只会给第一项权利'ReadyForPickups[0]'【参考方案2】:

您的 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>
);

【讨论】:

以上是关于如何在本机反应中解析json数据的主要内容,如果未能解决你的问题,请参考以下文章

如何在本机反应中从平面列表中设置 Json 数组

在本机反应中从 json 对象访问特定数据

通过 json 数据反应原生动态主题

通过Mysql解析本机json

我如何在本机反应中从 json 中选择特定值?

如何编写重用通用 JavaScript 代码的反应原生“本机模块”(桥)?