1

I have a URL with a string which I want to JSON.parse it (I'm new at React native).

here is part of the URL with the string -

<string>[{"Song_ID":"11","Song_Name":"The Doors - People","Song_File":"http://myurl.com/songs/The_Doors_People.mp3","Image":"http://myurl.com/images/The_Doors.jpg"},{"Song_ID":"12","Song_Name":"Smashing Pumpkins - Porcelina","Song_File":"http://myurl.com/songs/Smashing_Pumpkins_Porcelina.mp3","Image":"http://myurl.com/images/Mellon_Collie.jpg"},]</string>

Here is the code, I believe the fetch has the problem. The dataSource: JSON.parse(responseJson) doesn't do the job.

const URL =
  "http://mobile.domain.com/site/WebService.asmx/SongsList";


export default class FetchExample extends React.Component {
  static navigationOptions = {
    title: "Json Data"
  };
  constructor(props) {
    super(props);
    this.state = { isLoading: true };
  }

  componentDidMount() {
    return fetch(URL)
      .then(response => response.json())
      .then(responseJson => {
        this.setState(
          {
            isLoading: false,
            dataSource: JSON.parse(responseJson) // doesn't work
          },
          function() {}
        );
      })
      .catch(error => {
        console.error(error);
      });
  }

I tried dataSource: JSON.stringify(responseJson) but it doesn't do the job also. The render code - (I hope this part is o.k - data={this.state.dataSource})

   render(){

    if(this.state.isLoading){
      return(
        <View style={{flex: 1, padding: 20}}>
          <ActivityIndicator/>
        </View>
      )
    }

    return(
      <View style={{flex: 1, paddingTop:20}}>
        <FlatList
          data={this.state.dataSource}
          renderItem={({item}) => <Text>{item.Song_ID}, {item.Song_Name}</Text>}
          keyExtractor={({id}, index) => id} // this part with the "id" and "index" I dont understand (the index in my code is fade)
        />
      </View>
    );
  }
}

it shows me the error: " JSON Parse error: Unrecognized token '<' ".

ExtraSun
  • 528
  • 2
  • 11
  • 31
  • the error means the json you're trying to parse isn't valid. your data has 2 potential issues at a brief glance the tags are not valid json and the trailing comma at the end will also cause validation to fail. – digital-pollution Oct 30 '18 at 16:38
  • 1
    Does the response actually include the '' tags? If so that's you're problem and you'll have to parse those tags out of the string before using `JSON.parse` – SimplyComplexable Oct 30 '18 at 16:40
  • should also add the the parsing will fail if it's already json. JSON.parse is for turning strings into json. – digital-pollution Oct 30 '18 at 16:41
  • This ` .then(response => response.json()) .then(responseJson => { this.setState( { isLoading: false, dataSource: responseJson }, ); })` made the same error – ExtraSun Oct 30 '18 at 16:45
  • 1
    See the below answer. You're not getting valid JSON back from your request. I would check the network tab to see what response you're getting. – SimplyComplexable Oct 30 '18 at 16:59

2 Answers2

2

it shows me the error: " JSON Parse error: Unrecognized token '<' ".

That means what you're trying to parse isn't JSON. So you'll want to use the browser's Network tab to see what it is.

If it's really what you have in your question:

[{"Song_ID":"11","Song_Name":"The Doors - People","Song_File":"http://myurl.com/songs/The_Doors_People.mp3","Image":"http://myurl.com/images/The_Doors.jpg"},{"Song_ID":"12","Song_Name":"Smashing Pumpkins - Porcelina","Song_File":"http://myurl.com/songs/Smashing_Pumpkins_Porcelina.mp3","Image":"http://myurl.com/images/Mellon_Collie.jpg"},]

Then there are two problems with it:

  1. The <string> at the start and the </string> at the end (and that fits your error message), and

  2. In JSON, you can't have a trailing comma in an array.

Here's the correct JSON version of that:

[{"Song_ID":"11","Song_Name":"The Doors - People","Song_File":"http://myurl.com/songs/The_Doors_People.mp3","Image":"http://myurl.com/images/The_Doors.jpg"},{"Song_ID":"12","Song_Name":"Smashing Pumpkins - Porcelina","Song_File":"http://myurl.com/songs/Smashing_Pumpkins_Porcelina.mp3","Image":"http://myurl.com/images/Mellon_Collie.jpg"}]

Another possibility is that you're not getting the JSON you think you are at all, and instead it's an error message from the server as HTML (given that < character). (The HTML may well be reporting an error, see #4 below.)

But you have two other problems:

  1. You're trying to double-parse the JSON:

    componentDidMount() {
      return fetch(URL)
        .then(response => response.json()) // <=== Parses the JSON
        .then(responseJson => {
          this.setState(
            {
              isLoading: false,
              dataSource: JSON.parse(responseJson) // <=== Tries to parse it again
            },
            function() {}
          );
        })
        .catch(error => {
          console.error(error);
        });
    }
    

    Only parse it once.

  2. Your code needs to check response.ok. You're not alone in missing out this check, it's so common that people miss it out that I wrote it up on my anemic little blog.

So (see *** comments):

componentDidMount() {
  return fetch(URL)
    .then(response => {
        if (!response.ok) {                      // *** Check errors
            throw new Error(                     // ***
                "HTTP status " + response.status // ***
            );                                   // ***
        }                                        // ***
        return response.json();                  // *** Parse the JSON (once)
    })
    .then(dataSource => {                        // *** More accurate name
      this.setState(
        {
          isLoading: false,
          dataSource                             // *** Use the parsed data
        },
        function() {}
      );
    })
    .catch(error => {
      console.error(error);
    });
}

In a comment you've said:

I can't remove the tag , it comes from c# url WebService.asmx

You should be able to fix that in WebService.asmx. ASP.net absolutely can produce valid JSON. Otherwise, you can't directly parse it as JSON.

But — and I don't recommend this — if absolutely necessary, you can pre-process the string to deal with the two issues I pointed out with it:

componentDidMount() {
  return fetch(URL)
    .then(response => {
        if (!response.ok) {                      // *** Check errors
            throw new Error(                     // ***
                "HTTP status " + response.status // ***
            );                                   // ***
        }                                        // ***
        return response.text();                  // *** Read the TEXT of the response
    })
    .then(dataSourceText => {                    // *** More accurate name
      // *** Remove the invalid parts and parse it
      const dataSource = JSON.parse(
        dataSourceText.match(/^<string>(.*),]<\/string>$/)[1] + "]"
      );
      this.setState(
        {
          isLoading: false,
          dataSource                             // *** Use the parsed data
        },
        function() {}
      );
    })
    .catch(error => {
      console.error(error);
    });
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • I copies your "componentDidMount() { return fetch(URL)" code and it made error on the visual code software, can't solve them – ExtraSun Oct 30 '18 at 17:02
  • 1
    @sup.DR - It was a simple missing `)`. I've fixed it. (I've also expanded the beginning of the answer.) But the point isn't to copy-and-paste code from answers hoping it will work. The point is to *understand* what the code is doing, and why, and apply those lessons to your code. – T.J. Crowder Oct 30 '18 at 17:04
  • @sup.DR - I've added an example at the end of pre-processing the string, but really, this needs fixing server-side. – T.J. Crowder Oct 30 '18 at 17:15
  • Sorry but I still can't solve the problem. I took this code - Using StringBuilder - https://stackoverflow.com/questions/17398019/convert-datatable-to-json-in-c-sharp. (/^(.*),]<\/string>$/)[1] + "]" made error: null is not an object – ExtraSun Oct 30 '18 at 17:43
0

Seems that the problem is that the reponse contains the tag <string></string>. I think that if u remove then first should work.

Like in this question.

Gois
  • 88
  • 1
  • 8
  • *"Like in this question."* If you think a question is a duplicate of another question, don't answer it. Instead, when you have enough rep, post a comment, and later when you have more rep, vote to close as a duplicate. Until then, *be patient*, the system is designed this way for a reason. – T.J. Crowder Oct 30 '18 at 16:44
  • I can't remove the tag , it comes from c# url WebService.asmx – ExtraSun Oct 30 '18 at 17:05
  • @sup.DR - You should be able to fix that in WebService.asmx. ASP.net absolutely **can** produce valid JSON. Otherwise, you can't directly parse it as JSON. – T.J. Crowder Oct 30 '18 at 17:09
  • I have this - DataTable To Json Obj code - https://stackoverflow.com/questions/17398019/convert-datatable-to-json-in-c-sharp and It came this way (52 vots) – ExtraSun Oct 30 '18 at 17:35