Как вызвать свойство объекта с пустым именем свойства?

У меня есть следующий JSON, и я не могу его контролировать, поскольку он поступает из внешнего API:

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

Я использую десериализатор JSON (JSON.Net), чтобы превратить его в динамический объект.

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

Дело в том, что один из ключей json - это пустая строка "". Теперь я не могу назвать это свойство как таковое:

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

Как мне вызвать вещи под ним, когда одна из верхних клавиш пуста? Выполнить devices..sessions не получилось.


person Amin Husni    schedule 28.10.2017    source источник
comment
В отличие от JavaScript, в C # синтаксически вы не можете определить свойство без имени. Лучше всего использовать собственный декодер или свойства цикла, пока вы не получите тот, который вам нужен. stackoverflow.com/ questions / 957783 /   -  person S. Walker    schedule 28.10.2017
comment
Аналогичный вопрос: десериализовать пустое имя свойства json   -  person Lance U. Matthews    schedule 28.10.2017
comment
Плюс: Ваши скобки не сбалансированы: массив соединений не закрыт.   -  person wp78de    schedule 28.10.2017


Ответы (3)


Вы можете использовать синтаксис квадратных скобок для доступа к свойству с пустым ключом. Например:

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

Скрипка: https://dotnetfiddle.net/H4orMZ

person Brian Rogers    schedule 28.10.2017

Первая проблема, которую я обнаружил: ваш образец страдает несбалансированными скобками:
После "connections": [ не приходит закрытие ]

В любом случае, это выполнимо:

... используя такой динамический объект:

dynamic values = JsonConvert.DeserializeObject<dynamic>(json);
var ip = values.devices[""].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; }
}

Итак, ключ устройств - это пустая строка, но это нормально.

Попробуйте прямо сейчас здесь. Вывод:

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;

Полный код:

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; }
}
person wp78de    schedule 28.10.2017

Лучший способ решить эту проблему - изменить строку mes следующим образом:

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

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

Думаю, тогда вы сможете получить доступ

values.devices.prop.sessions.connections
person Sourav Bhattacharya    schedule 28.10.2017
comment
Вызов Replace() выдает ArgumentException, потому что вы не можете пройти пустой поиск string. Вам нужны кавычки, окружающие как поисковый, так и заменяющий текст: mes.Replace("\"\"","\"prop\""). Кроме того, если входной JSON содержал свойство, установленное на пустую строку, это также заменило бы это значение. - person Lance U. Matthews; 28.10.2017
comment
Замена строки определенно не лучший способ. - person Brian Rogers; 28.10.2017