Member 14647867 Ответов: 2

Проверьте, чтобы увидеть, если объект в массив JSON является также массив


Привет,

У меня есть JSON-файл, который содержит массив каналов для устройства. Но если это приспособление имеет несколько ячеек, некоторые из каналов должны быть повторены. Мой JSON-файл делает это, имея массив каждой ячейки, а затем еще один массив каналов, которые должны быть повторены для каждой ячейки. Эти два массива находятся внутри массива внутри массива основных каналов. Мне нужен способ проверить, есть ли внутри массива основных каналов другой массив, чтобы определить, имеет ли прибор несколько ячеек или нет. Я не могу изменить файл JSON, так как он поступает из другого источника, и я хочу, чтобы файлы приспособлений были легко обновляемы.

Это мой JSON:

{
      "name": "16: Effect RGB",
      "channels": [
        "Dimmer Master",
        "Strobe Master",
        "Programs",
        "Program Speed",
        "Program Fade Time",
        "Program Direction",
        "Program Group Size",
        "Group Offset",
        "Restart Program",
        {
          "insert": "matrixChannels",
          "repeatFor": [
            "Effect Color 1",
            "Effect Color 2",
            "Effect Color 3",
            "Effect Color 4"
          ],
          "channelOrder": "perPixel",
          "templateChannels": [
            "Red $pixelKey",
            "Green $pixelKey",
            "Blue $pixelKey"
          ]
        }
      ]
    },


Что я уже пробовал:

Я действительно не знаю, как это проверить в C#. Я могу заставить его проверить, сколько элементов находится в основном массиве каналов, но затем, очевидно, когда дело доходит до массива внутри массива каналов, он выплевывает ошибку. Любая помощь будет оценена по достоинству! Ваше здоровье!

Richard MacCutchan

- он выплевывает ошибку."
Что такое "это" и в чем ошибка?

Member 14647867

Извините, что это ошибка: Newtonsoft.Json.JsonReaderException: 'неожиданный символ, встреченный при разборе значения: {. Path 'modes[15].channels[8]', строка 1666, позиция 9.'

Richard MacCutchan

Предполагая, что это действительно так: {. Path 'modes[15].channels[8]' тогда либо полная остановка после открывающей скобки, либо одинарная кавычка перед режимами-это chcharacter 9. Я подозреваю, что ни один из них не принадлежит к строке JSON.

2 Ответов

Рейтинг:
2

Simon_Whale

Обычно я бы опреснял строку JSON в модель C# и использовал для этого C#, используя Newton

Newton Json -десериализация объекта[^]


Если вы не хотите этого делать и предпочитаете использовать сам JSON я бы посмотрел на это

Получение значений из объекта JSON[^]


Richard MacCutchan

Смотрите комментарии выше, OP уже использует NewtonSoft.

Member 14647867

Проблема здесь в том, что у меня есть массивы внутри массивов внутри массивов, и мне нужно проверить тип, чтобы увидеть, является ли он объектом или массивом

Richard MacCutchan

Ньютонсофт сделает это за вас. Ваша проблема заключается в том, что текст JSON содержит недопустимые символы, поэтому синтаксический анализ завершается неудачей.

Simon_Whale

Я проверил образец, который вы дали выше, в онлайн-валидаторе Json (https://jsonlint.com) и он не вернул никаких ошибок. Поэтому я думаю, что вам нужно будет пересмотреть модели, которые вы анализируете.

Рейтинг:
1

Richard Deeming

Проблема в том, что ваш channels массив содержит смесь строк и объектов. Javascript не имеет с этим проблем, потому что он слабо типизирован. Но C#-это строго типизированный язык, и у него нет собственного представления чего-то, что может быть либо одним типом, либо другим.

Вы могли бы потенциально использовать LINQ to JSON[^] для доступа к данным в свободно типизированном виде.

В противном случае вам понадобится JsonConverter. Например:

public class ChannelData
{
    public string Insert { get; set; }
    public string[] RepeatFor { get; set; }
    public string ChannelOrder { get; set; }
    public string[] TemplateChannels { get; set; }
}

[JsonConverter(typeof(ChannelConverter))]
public class Channel
{
    public string Value { get; set; }
    public ChannelData Data { get; set; }
}

public class ChannelConverter : JsonConverter
{
    public override bool CanRead => true;
    public override bool CanWrite => true;
    public override bool CanConvert(Type objectType) => objectType == typeof(Channel);
    
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);
        switch (token.Type)
        {
            case JTokenType.Null:
            {
                return null;
            }
            case JTokenType.String:
            {
                return new Channel { Value = (string)token };
            }
            case JTokenType.Object:
            {
                return new Channel { Data = token.ToObject<ChannelData>() };
            }
            default:
            {
                throw new NotSupportedException();
            }
        }
    }
    
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        switch (value)
        {
            case null:
            {
                writer.WriteNull();
                break;
            }
            case Channel c when c.Value is string s:
            {
                writer.WriteValue(s);
                break;
            }
            case Channel c when c.Data is ChannelData data:
            {
                serializer.Serialize(writer, data);
                break;
            }
            case Channel:
            {
                writer.WriteNull();
                break;
            }
            default:
            {
                throw new NotSupportedException();
            }
        }
    }
}

public class Fixture
{
    public string Name { get; set; }
    public Channel[] Channels { get; set; }
}
При том, что в месте, ваш пример JSON будет правильно десериализовать к Fixture объект. Вы также можете ресериализовать его, чтобы получить тот же результат.