1

I have the following JSON and I have no control over it since it comes from an external API:

    {
  "user_id": "something_name",
  "devices": {
    "": {
      "sessions": [
        {
          "connections": [
            {
              "ip": "225.225.225.225",
              "user_agent": "something",
              "last_seen": 1504266816737
            }
        }
      ]
    }
  }
}

I am using a JSON deserializer(JSON.Net) to make it into a dynamic object.

dynamic values = JsonConvert.DeserializeObject<dynamic>(mes);

The thing is, one of the json key is an empty string "". Now I can't seem to call the property as such:

values.devices.<the empty string part>.sessions.connections

How do I call things below it when one of the top key is empty? Doing devices..sessions did not work.

Amin Husni
  • 148
  • 1
  • 1
  • 10
  • Unlike JavaScript, in c# syntactically you can't define a property without a name. Your best bet may be to use a custom decoder, or loop properties til you get the one you want. https://stackoverflow.com/questions/957783/loop-through-an-objects-properties-in-c-sharp – S. Walker Oct 28 '17 at 02:36
  • Similar question: [Deserialize empty json propertyname](https://stackoverflow.com/q/14169350/150605) – Lance U. Matthews Oct 28 '17 at 02:42
  • 1
    Plus: Your brackets are not balanced: connections array is not closed. – wp78de Oct 28 '17 at 04:31

4 Answers4

5

You can use square bracket syntax to access the property with the empty key. For example:

dynamic ip = values.devices[""].sessions[0].connections[0].ip;

Fiddle: https://dotnetfiddle.net/H4orMZ

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
2

The first issue I discovered: Your sample suffers from unbalanced brackets:
After "connections": [ comes no closing ]

Anyways, it is doable:

...using a dynamic object like that:

dynamic values = JsonConvert.DeserializeObject<dynamic>(json);
var ip = values.devices[""].sessions[0].connections[0].ip;

...with a custom class definitions as shown below:

public class RootObject
{public string user_id { get; set; }
    public Dictionary<string, Devices> devices { get; set; }
}
public class Devices
{
    public List<Session> sessions { get; set; }
}
public class Session
{
    public List<Connections> connections { get; set; }
}
public class Connections
{
    public string ip { get; set; }
    public string user_agent { get; set; }
    public long last_seen { get; set; }
}

So, the Devices Key is an empty string - but that's fine.

Try it live here. Output:

Deserializing json...
Success!
  Device Key   #: 
  Device Value #: Devices
            IP #: 225.225.225.225 (just a sample sub-property)

using System;
using Newtonsoft.Json;
using System.Collections.Generic;

Full code:

public class Program
{
    public static void Main()
    {
        string json = @"{
                          ""user_id"": ""something_name"",
                          ""devices"": {
                            """": {
                              ""sessions"": [
                                {
                                  ""connections"": [
                                    {
                                      ""ip"": ""225.225.225.225"",
                                      ""user_agent"": ""something"",
                                      ""last_seen"": 1504266816737
                                    }
                                  ]
                                }
                              ]
                            }
                          }
                        }";

        Console.WriteLine("Deserializing json...");

        //dynamic values = JsonConvert.DeserializeObject<dynamic>(json);
        //var ip = values.devices[""].sessions[0].connections[0].ip;

        RootObject o = JsonConvert.DeserializeObject<RootObject>(json, new JsonSerializerSettings
        {
            MissingMemberHandling = MissingMemberHandling.Ignore, 
            NullValueHandling = NullValueHandling.Ignore //these settings are not important here
        });
        Console.WriteLine("Success!");
        foreach (var dev in o.devices)
        {
            Console.WriteLine("  Device Key   #: {0}", dev.Key);
            Console.WriteLine("  Device Value #: {0}", dev.Value);
            Console.WriteLine("            IP #: {0}", dev.Value.sessions[0].connections[0].ip);
        }
    }
}

public class RootObject
{public string user_id { get; set; }
    public Dictionary<string, Devices> devices { get; set; }
}
public class Devices
{
    public List<Session> sessions { get; set; }
}
public class Session
{
    public List<Connections> connections { get; set; }
}
public class Connections
{
    public string ip { get; set; }
    public string user_agent { get; set; }
    public long last_seen { get; set; }
}
wp78de
  • 18,207
  • 7
  • 43
  • 71
1

Another solution is you can set the property name of json value in your code like this :

{
  "errors": {
    "": [
      " invalid request"
    ]
  },
  "title": "One or more validation errors occurred.",
  "status": 400
}

And the Model is like this :

 [JsonPropertyName("")]
 public List<string> systemErrors { get ; set; } = new List<string>();
Ehsan Akbar
  • 6,977
  • 19
  • 96
  • 180
-3

The best way to solve this problem is to modify the mes string like :

string modifiedmes = mes.Replace("","prop");

dynamic values = JsonConvert.DeserializeObject<dynamic>(modifiedmes);

I guess then you will be able to access

values.devices.prop.sessions.connections
  • The call to `Replace()` throws an `ArgumentException` because you cannot pass an empty search `string`. You need quotes surrounding both the search and replacement text: `mes.Replace("\"\"","\"prop\"")`. Also, if the input JSON contained a property set to an empty string this would replace that value as well. – Lance U. Matthews Oct 28 '17 at 04:15
  • Doing a string replace is definitely *not* "the best way". – Brian Rogers Oct 28 '17 at 05:22