Search code examples
c#jsonvisual-studio-2019

Unable to correctly parse JSON body


I am successfully able to retrieve the JSON body from a URL in Visual Studio 2019 using Newtonsoft library. However I'm having difficulty in parsing out the only variable I am interested in.

I've tried to follow some guides on here that I don't seem to have either implemented correctly or haven't fully understood (I'm pretty new to this). e.g. Unexpected character encountered while parsing API response

RAW JSON:

{ 
"deviceId":37,
"longMacAddress":"5884e40000000439",
"shortMacAddress":259,
"hoplist":"(259,3)",
"associationTime":"2019-06-10 22:43:54",
"lifeCheckInterval":5,
"lastLiveCheck":"2019-06-11 07:11:37",
"onlineStatus":1,
"txPowerValue":14,
"deviceType":1,
"frequencyBand":1,
"lastLivecheck":"2019-06-11 07:11:36",
"disassociationState":0,
"firmwareUpdateActivated":0,
"firmwareUpdatePackagesSent":0,
"firmwareUpdatePackagesUnsent":0,
"firmwareUpdateInProgress":0,
"deviceIdOem":"-1",
"deviceNameOem":"-1",
"deviceCompanyOem":"-1",
"binaryInputCount":0,
"binaryOutputCount":0,
"analogInputCount":0,
"characterStringCount":1,
"location":[
  {
    "location":"UK",
    "locationWriteable":1,
    "changedAt":"2019-06-10 23:40:50"
   }
],
"description": [
  {
    "description":"DevKit",
    "descriptionWriteable":1,
    "changedAt":"2019-06-10 23:40:54"
  }
],
"binaryInput":[],
"binaryOutput":[],
"analogInput":[],
"characterString": [
 {
   "characterString":"149+0.0+99+26.5+0",
   "characterStringWriteable":1,
   "changedAt":"2019-06-11 06:45:02"
  }
]
}

MY MAIN CODE:

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace API_JSON_1
{
    class Program
    {
        static void Main(string[] args)
        {
            var client = new WebClient();
            var JSON = client.DownloadString("http://192.168.0.254:8000/nodes/longmac/5884e40000000439");
            Console.WriteLine(JSON);
            Console.WriteLine("----------------------------------------------");
            CharacterString CSV = JsonConvert.DeserializeObject<CharacterString>(JSON);
            Console.WriteLine("Sensor data: " + CSV.CharacterStringCharacterString);
        }
    }
}

MY CHARACTER STRING CLASS:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace API_JSON_1
{
    public class CharacterStrings
    {
        public CharacterStrings CharString { get; set; }
    }

    public class CharacterString
    {   public string CharacterStringCharacterString { get; set; }
        public long CharacterStringWriteable { get; set; }
        public DateTimeOffset ChangedAt { get; set; }
    }
}

OUTPUT TO THE CONSOLE:

{"deviceId":37,"longMacAddress":"5884e40000000439","shortMacAddress":259,"hoplis
t":"(259,3)","associationTime":"2019-06-10 22:43:54","lifeCheckInterval":5,"last
LiveCheck":"2019-06-11 06:56:37","onlineStatus":1,"txPowerValue":14,"deviceType"
:1,"frequencyBand":1,"lastLivecheck":"2019-06-11 06:56:33","disassociationState"
:0,"firmwareUpdateActivated":0,"firmwareUpdatePackagesSent":0,"firmwareUpdatePac
kagesUnsent":0,"firmwareUpdateInProgress":0,"deviceIdOem":"-1","deviceNameOem":"
-1","deviceCompanyOem":"-1","binaryInputCount":0,"binaryOutputCount":0,"analogIn
putCount":0,"characterStringCount":1,"location":[{"location":"UK","locati
onWriteable":1,"changedAt":"2019-06-10 23:40:50"}],"description":[{"description"
:"DevKit","descriptionWriteable":1,"changedAt":"2019-06-10 23:40:54"}],"binaryIn
put":[],"binaryOutput":[],"analogInput":[],"characterString":[{"characterString"
:"149+0.0+99+26.5+0","characterStringWriteable":1,"changedAt":"2019-06-11 06:45:
02"}]}
----------------------------------------------
Sensor data:
Press any key to continue . . .

Obviously I was expecting/hoping that the penultimate line there would read: "Sensor data: 149+0.0+99+26.5+0"


Solution

  • Welcome to StackOverflow!

    Something you need to keep in mind when converting a json string to an object (ie: Deserialize) is that the object to which you are converting the string into needs to match the format of the json string. In your case, the json string does not match the object to which you are converting.

    Once you have the correct object, this will give you the output you want:

        static void Main(string[] args)
        {
            string JSON = "{\"deviceId\":37,\"longMacAddress\":\"5884e40000000439\",\"shortMacAddress\":259,\"hoplist\":\"(259,3)\",\"associationTime\":\"2019-06-10 22:43:54\",\"lifeCheckInterval\":5,\"lastLiveCheck\":\"2019-06-11 07:11:37\",\"onlineStatus\":1,\"txPowerValue\":14,\"deviceType\":1,\"frequencyBand\":1,\"lastLivecheck\":\"2019-06-11 07:11:36\",\"disassociationState\":0,\"firmwareUpdateActivated\":0,\"firmwareUpdatePackagesSent\":0,\"firmwareUpdatePackagesUnsent\":0,\"firmwareUpdateInProgress\":0,\"deviceIdOem\":\"-1\",\"deviceNameOem\":\"-1\",\"deviceCompanyOem\":\"-1\",\"binaryInputCount\":0,\"binaryOutputCount\":0,\"analogInputCount\":0,\"characterStringCount\":1,\"location\":[{\"location\":\"UK\",\"locationWriteable\":1,\"changedAt\":\"2019-06-10 23:40:50\"}],\"description\":[{\"description\":\"DevKit\",\"descriptionWriteable\":1,\"changedAt\":\"2019-06-10 23:40:54\"}],\"binaryInput\":[],\"binaryOutput\":[],\"analogInput\":[],\"characterString\":[{\"characterString\":\"149+0.0+99+26.5+0\",\"characterStringWriteable\":1,\"changedAt\":\"2019-06-11 06:45:02\"}]}";
            Console.WriteLine(JSON);
            Console.WriteLine("----------------------------------------------");
            RootObject CSV = JsonConvert.DeserializeObject<RootObject>(JSON);
    
            // Option 1: Loop over the items in your List<CharacterString>...
    
            foreach (var cs in CSV.characterString)
            {
                Console.WriteLine("Sensor data: " + cs.characterString);
            }
    
            // Option 2: Or, if you know there is only one in the list...
    
            Console.WriteLine("Sensor data: " + CSV.characterString.First().characterString);
       }
    

    EDIT to explain the code above: Because characterString is a List<CharacterString>, it's technically possible that you could have more than one item in that list. Option 1: If you want, you can loop through that list to display the items in it. But if you know for certain that there will only be one item in the list, then, Option 2: You can just display the .First() item in the list.

    I took the json sting you gave us, and using this handy website (http://json2csharp.com/#) I converted it into the following classes:

    public class RootObject
    {
        public int deviceId { get; set; }
        public string longMacAddress { get; set; }
        public int shortMacAddress { get; set; }
        public string hoplist { get; set; }
        public string associationTime { get; set; }
        public int lifeCheckInterval { get; set; }
        public string lastLiveCheck { get; set; }
        public int onlineStatus { get; set; }
        public int txPowerValue { get; set; }
        public int deviceType { get; set; }
        public int frequencyBand { get; set; }
        public string lastLivecheck { get; set; }
        public int disassociationState { get; set; }
        public int firmwareUpdateActivated { get; set; }
        public int firmwareUpdatePackagesSent { get; set; }
        public int firmwareUpdatePackagesUnsent { get; set; }
        public int firmwareUpdateInProgress { get; set; }
        public string deviceIdOem { get; set; }
        public string deviceNameOem { get; set; }
        public string deviceCompanyOem { get; set; }
        public int binaryInputCount { get; set; }
        public int binaryOutputCount { get; set; }
        public int analogInputCount { get; set; }
        public int characterStringCount { get; set; }
        public List<Location> location { get; set; }
        public List<Description> description { get; set; }
        public List<object> binaryInput { get; set; }
        public List<object> binaryOutput { get; set; }
        public List<object> analogInput { get; set; }
        public List<CharacterString> characterString { get; set; }
    }
    
    public class Location
    {
        public string location { get; set; }
        public int locationWriteable { get; set; }
        public string changedAt { get; set; }
    }
    
    public class Description
    {
        public string description { get; set; }
        public int descriptionWriteable { get; set; }
        public string changedAt { get; set; }
    }
    
    public class CharacterString
    {
        public string characterString { get; set; }
        public int characterStringWriteable { get; set; }
        public string changedAt { get; set; }
    }