简体   繁体   中英

Can't parse JSON object with Newtonsoft.JSON

I have a problem with parsing following JSON object:

{ 
    "SERVER1/DeviceIpint.3/SourceEndpoint.video:0:0" : 
    {
        "origin" : "SERVER1/DeviceIpint.3/SourceEndpoint.video:0:0",
        "state" : "connected",
        "friendlyNameLong" : "Camera 3",
        "friendlyNameShort" : "3"
    },
    "SERVER2/DeviceIpint.5/SourceEndpoint.video:0:0" : 
    {
        "origin" : "SERVER2/DeviceIpint.5/SourceEndpoint.video:0:0",
        "state" : "disconnected",
        "friendlyNameLong" : "Camera 5", 
        "friendlyNameShort" : "5" 
    },
    ...

As far as i know, this Server1..., Server2... shouldn't be variables, there should be written "server" or something like that. I am using Newtonsoft.JSON to parse this data but i can't deserialize it. I always get null values. For example, this is my VideoSource class

  private class VideoSource
  {
       public string origin { get; set; }
       public string state { get; set; }
       public string friendlyNameLong { get; set; }
       public string friendlyNameShort { get; set; }

       public override string ToString()
       {
           return origin;
       }
   }

and I'm trying to parse it with following function:

private VideoSource ParseJsonToVideoSource(string obj)
{
    dynamic source = JsonConvert.DeserializeObject(obj);

    VideoSource s = new VideoSource();
    s.origin = source.origin;
    s.friendlyNameLong = source.friendlyNameLong;
    s.friendlyNameShort = source.friendlyNameShort;
    s.state = source.state;

    return s;
}

As I said, i get null values. What's wrong?

Working LinqPad example:

void Main()
{
    string obj = @"{ 
        ""SERVER1/DeviceIpint.3/SourceEndpoint.video:0:0"" : 
        {
            ""origin"" : ""SERVER1/DeviceIpint.3/SourceEndpoint.video:0:0"",
            ""state"" : ""connected"",
            ""friendlyNameLong"" : ""Camera 3"",
            ""friendlyNameShort"" : ""3""
        },
        ""SERVER2/DeviceIpint.5/SourceEndpoint.video:0:0"" : 
        {
            ""origin"" : ""SERVER2/DeviceIpint.5/SourceEndpoint.video:0:0"",
            ""state"" : ""disconnected"",
            ""friendlyNameLong"" : ""Camera 5"", 
            ""friendlyNameShort"" : ""5"" 
        }
    }";

    VideoSource s = new VideoSource();
    dynamic source = JsonConvert.DeserializeObject<Dictionary<string, VideoSource>>(obj);
    foreach(var videoSource in source)
    {
        s.origin = videoSource.Value.origin;
        s.friendlyNameLong = videoSource.Value.friendlyNameLong;
        s.friendlyNameShort = videoSource.Value.friendlyNameShort;
        s.state = videoSource.Value.state;
        s.Dump();
    }
}

// Define other methods and classes here
public class VideoSource
{
    public string origin { get; set; }
    public string state { get; set; }
    public string friendlyNameLong { get; set; }
    public string friendlyNameShort { get; set; }

    public override string ToString()
    {
        return origin;
    }
}

A simple way would be this:

dynamic source = JsonConvert.DeserializeObject<ExpandoObject>(json);
foreach(var videoSource in source)
{
    // Here you can access videoSource.origin, videoSource.state etc.
}

An ExpandoObject is actually just a dictionary, so you could also deserialize into a dictionary with your VideoSource as the value:

var videoSources = JsonConvert.DeserializeObject<Dictionary<string, VideoSource>>(json);
foreach(var videoSource in source)
{
    // videoSource is of type VideoSource
}

(This has already been noted by Mateusz in his comment )

I'd form an array out of it like this:

[
    {
        "origin": "SERVER1/DeviceIpint.3/SourceEndpoint.video:0:0",
        "state": "connected",
        "friendlyNameLong": "Camera 3",
        "friendlyNameShort": "3"
    },
    {
        "origin": "SERVER2/DeviceIpint.5/SourceEndpoint.video:0:0",
        "state": "disconnected",
        "friendlyNameLong": "Camera 5",
        "friendlyNameShort": "5"
    }
]

and deserialize it like this:

var result = JsonConvert.DeserializeObject<List<VideoSource>>(jsonString);

Then it should work!

UPDATE

When you have no control over your json, do it this way:

string json =
            "{\"SERVER1/DeviceIpint.3/SourceEndpoint.video:0:0\":{\"origin\":\"SERVER1/DeviceIpint.3/SourceEndpoint.video:0:0\",\"state\":\"connected\",\"friendlyNameLong\":\"Camera 3\",\"friendlyNameShort\":\"3\"},\"SERVER2/DeviceIpint.5/SourceEndpoint.video:0:0\":{\"origin\":\"SERVER2/DeviceIpint.5/SourceEndpoint.video:0:0\",\"state\":\"disconnected\",\"friendlyNameLong\":\"Camera 5\",\"friendlyNameShort\":\"5\"}}";

dynamic result = JsonConvert.DeserializeObject(json);
foreach (JProperty property in result)
{
    var myVideoSource = JsonConvert.DeserializeObject<VideoSource>(property.Value.ToString());
}

Your json data is actually list like dictionary key value pair. Key is server name. You can parse like this.

        public Dictionary<string, VideoSource> ParseJsonToVideoSource(string obj)
        {
            Dictionary<string, VideoSource> result = new Dictionary<string, VideoSource>();
            dynamic sources = JsonConvert.DeserializeObject(obj);

            foreach (var source in sources)
            {
                VideoSource s = new VideoSource();
                s.origin = source.Value.origin;
                s.friendlyNameLong = source.Value.friendlyNameLong;
                s.friendlyNameShort = source.Value.friendlyNameShort;
                s.state = source.Value.state;

                result.Add(source.Name, s);
            }

            return result;
        }

but i think, json has to be like this.

[ 
{"name":"SERVER1/DeviceIpint.3/SourceEndpoint.video:0:0",
"info" :
{
    "origin" : "SERVER1/DeviceIpint.3/SourceEndpoint.video:0:0",
    "state" : "connected",
    "friendlyNameLong" : "Camera 3",
    "friendlyNameShort" : "3"
}},
{name:"SERVER2/DeviceIpint.5/SourceEndpoint.video:0:0",
info:
{
    "origin" : "SERVER2/DeviceIpint.5/SourceEndpoint.video:0:0",
    "state" : "disconnected",
    "friendlyNameLong" : "Camera 5", 
    "friendlyNameShort" : "5" 
}}]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM