0

In this method, a JSON String will be returned from GetDataSetColumns() which called API from a Signage System(Xibo) to get dataset. And I want to parse it to JSON Object.

I googled it many times and found some people have same problem too. But it seems their solution are not working for me. Such as parsing to JArray or String.Trim()

public async Task<String> GetColumnIdByName(int dataSetId, String heading)
        {
            String columns = await GetDataSetColumns(dataSetId);
            columns.Replace("[", "");
            columns.Replace("]", "");
            columns.TrimStart().TrimEnd();
            **JObject json = JObject.Parse(columns);** 
            Debug.WriteLine(json);

            foreach (KeyValuePair<string, JToken> pair in json)
            {
                if (pair.Key.ToString().Equals("dataSetColumnId"))
                {
                    if(pair.Value.ToString().Equals(heading))
                    {
                        return pair.Value.ToString();
                    }
                }
            }
            return null;
        }

Here's the JSON returned from GETDataSetColumns method and shown in Debug. And I cannot see there is any mistakes in this JSON String.

    [
    {
        "dataSetColumnId": 8,
        "dataSetId": 3,
        "heading": "item_name",
        "dataTypeId": 1,
        "dataSetColumnTypeId": 1,
        "listContent": null,
        "columnOrder": "1",
        "formula": null,
        "dataType": "String",
        "dataSetColumnType": "Value"
    },
    {
        "dataSetColumnId": 9,
        "dataSetId": 3,
        "heading": "price",
        "dataTypeId": 1,
        "dataSetColumnTypeId": 1,
        "listContent": null,
        "columnOrder": "2",
        "formula": null,
        "dataType": "String",
        "dataSetColumnType": "Value"
    },
    {
        "dataSetColumnId": 12,
        "dataSetId": 3,
        "heading": "category",
        "dataTypeId": 1,
        "dataSetColumnTypeId": 1,
        "listContent": null,
        "columnOrder": "3",
        "formula": null,
        "dataType": "String",
        "dataSetColumnType": "Value"
    },
    {
        "dataSetColumnId": 15,
        "dataSetId": 3,
        "heading": "status",
        "dataTypeId": 1,
        "dataSetColumnTypeId": 1,
        "listContent": null,
        "columnOrder": "7",
        "formula": null,
        "dataType": "String",
        "dataSetColumnType": "Value"
    }
]

And I also inspected the value of variable by Debugging mode, is it normal to have '\n' and many blankspaces? Moreover, the String.Replace and String.TrimStart() aren't working.

Debugging Mode

The exception error happens after JObject.Parse.

Exception thrown: 'Newtonsoft.Json.JsonReaderException' in Newtonsoft.Json.dll
Exception thrown: 'Newtonsoft.Json.JsonReaderException' in mscorlib.dll
An exception of type 'Newtonsoft.Json.JsonReaderException' occurred in mscorlib.dll but was not handled in user code
Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.

Is there any problem of my JSON string or the way of parsing? Thanks for any help!

tony1233465
  • 37
  • 1
  • 6
  • 1
    You are invalidating your json by removing [ and ]. What you have is an array and it is perfectly valid. No need to Trim either, blank space is not significant. – Palle Due Jan 10 '18 at 10:20
  • The JSON you've shown is already valid (you can check by inputting it at https://jsonlint.com/), you don't need to do anything to manipulate it, it's already parseable (since it's an array, JArray would be your best bet, if you don't have a specific type you want to deserialise to). – ADyson Jan 10 '18 at 10:58
  • If you don't know whether your `columns` string is going to be an object or an array, you can use [`JToken.Parse(columns)`](https://stackoverflow.com/q/38211719/3744182) and check the result. – dbc Jan 10 '18 at 16:45
  • I tried the original JSON without removing [ and ]. But the error JsonReaderException is still happneing. – tony1233465 Jan 11 '18 at 04:49

1 Answers1

0

I found the answer from this post

I also found other answers online but all of them are not working. Some of them proposed define a class and deserialize the object as that defined class. But I think it isn't the right way because the structure of JSON could be dynamic.

I transfer it to JArray and retrieve the objects from it as JObject. And it works. I saw these comments and I think the validity of JSON isn't the main point of my problem at all.

 String columns = await GetDataSetColumns(dataSetId);
 JArray jArr = (JArray)JsonConvert.DeserializeObject(columns);

 foreach (JObject item in jArr)
 { 
    if(heading.Equals(item["heading"].ToString()))
       {
                return item["dataSetId"].ToString();
       }

 }

Here's example of the JSON string and I get the value by key

{
    "dataSetColumnId": 12,
    "dataSetId": 3,
    "heading": "category",
    "dataTypeId": 1,
    "dataSetColumnTypeId": 1,
    "listContent": null,
    "columnOrder": "3",
    "formula": null,
    "dataType": "String",
    "dataSetColumnType": "Value"
}
tony1233465
  • 37
  • 1
  • 6