Десериализация JSON iin C# с использованием system.text. json с именем комплексного свойства - PullRequest
0 голосов
/ 12 февраля 2020

Я пытаюсь десериализовать JSON файлы, созданные сторонним инструментом.

Файлы содержат свойство, которое может выглядеть следующим образом:

"RECIPE": [{
        "ctPoint_0": {
            "endTemperature": 25,
            "hours": 0.07999999821186066,
            "startTemperature": 25
        },
        "ctPoint_1": {
            "endTemperature": 30,
            "hours": 0.07999999821186066,
            "startTemperature": 25
        },
        "ctPoint_2": {
            "endTemperature": 25,
            "hours": 0.07999999821186066,
            "startTemperature": 30
        },
        "pointCount": 3,
        "type": "CyclicTemp"
    }, {
        "cycles": 2,
        "type": "Repeat"
    }, {
        "cycles": 1,
        "duration": {
            "days": 0,
            "hours": 0
        },

    }]

Я использую system.text. json для десериализации:

newProgram = JsonSerializer.Deserialize<Program>(jsonString, options);

Извлечь моего класса Программы:

public class Program
    {

        public IList<Recipe> RECIPE { get; set; }
    }

Структура рецепта и cyclic_data:

public struct Cyclic_Data
    {
        public float endTemperature { get; set; }
        public float hours { get; set; }
        public float startTemperature { get; set; }

    }

    public struct Recipe
    {
        public int cycles { get; set; }

        // Would like to use this
        public IList<Cyclic_Data> ctPoints { get; set; }

        // this deserialises ok but obviously only to hardcoded limit
        public Cyclic_Data ctPoint_0 { get; set; }
        public Cyclic_Data ctPoint_1 { get; set; }
        public Cyclic_Data ctPoint_2 { get; set; }
        public Cyclic_Data ctPoint_3 { get; set; }
        public Cyclic_Data ctPoint_4 { get; set; }
        public Cyclic_Data ctPoint_5 { get; set; }
        public Cyclic_Data ctPoint_6 { get; set; }
        public Cyclic_Data ctPoint_7 { get; set; }
        public Cyclic_Data ctPoint_8 { get; set; }
        public Cyclic_Data ctPoint_9 { get; set; }
        public Cyclic_Data ctPoint_10 { get; set; }


        public Duration duration { get; set;}
        public string type { get; set; }
        public float temperature { get; set; }
        public int pointCount { get; set; }

    }

Согласно комментариям, если у меня есть несколько дискретных переменных типа Cyclic_Data, например, ctPoint_0, то это успешно десериализуется однако, поскольку этот список теоретически может быть сколь угодно большим, было бы бессмысленно пытаться объявить все возможные имена свойств.

Мне бы очень хотелось использовать IList для чтения всех значений ctPoint_X, но я изо всех сил пытаюсь найти способ сделать это. Вместо этого я смотрел на мягкую реализацию newton и задавался вопросом, можно ли использовать [JsonProperty ("name")] с RegEx для решения этой проблемы, но не смог найти ни одного успешного примера, сделанного таким образом.

Как можно десериализовать это разумным способом?

РЕДАКТИРОВАТЬ: В настоящее время я смотрю на пользовательский JsonNamingPolicy, чтобы переименовать любое имя свойства, соответствующее RegEx "^ ctPoint_ [0-9] + $ "ctPoints, сообщит вам, если это удастся, пожалуйста, прокомментируйте, если это обречено на неудачу или есть лучший способ ..

РЕДАКТИРОВАТЬ 2: Я попробовал метод, описанный выше, но он не работал поскольку правильный JSON для списка элементов не имеет названия в начале каждого элемента, однако это заставило меня думать о проблеме по-другому. В итоге я сделал несколько простых замен строк перед десериализацией. Это работало нормально :)

         int location;
            location = newText.IndexOf("\"ctPoint_0\":");

            newText = newText.Replace("\"ctPoint_0\":", "\"ctPoints\": [");
            if (location > 0)
            { int lastloc;

                for (int i = 1; i < 999999; i++)
                {
                    string nextString = "\"ctPoint_" + i.ToString() + "\": ";
                    lastloc = location;
                    location = newText.IndexOf(nextString);

                    newText = newText.Replace(nextString, "");
                    if (location == -1)
                    {
                        location = newText.IndexOf("}", lastloc);
                        newText = newText.Insert(location+1, "]");
                        break;
                    }
                }
               }

Спасибо

1 Ответ

0 голосов
/ 13 февраля 2020

Вы можете попробовать Dictionary<string, object> и проверить тип объекта во время выполнения

Вот модели, необходимые для этого сценария

public class CtPoint
{
    public int endTemperature { get; set; }
    public double hours { get; set; }
    public int startTemperature { get; set; }
}

public class Duration
{
    public int days { get; set; }
    public int hours { get; set; }
}

Вот пример кода Deserialize the JSON с использованием System.Text.Json.JsonSerializer

var results = System.Text.Json.JsonSerializer.Deserialize<List<Dictionary<string,object>>>(json);

foreach (var model in results)
{
    foreach(var item in model)
    {
        if (item.Key.Contains("ctPoint"))
        {
            var ctPoint = System.Text.Json.JsonSerializer.Deserialize<CtPoint>(item.Value.ToString());
            Console.WriteLine($"{item.Key}- {ctPoint.hours} {ctPoint.startTemperature} {ctPoint.endTemperature}");
        }
        else if (item.Key.Contains("duration"))
        {
            var duration = System.Text.Json.JsonSerializer.Deserialize<Duration>(item.Value.ToString());
            Console.WriteLine($"{item.Key}- {duration.days} {duration.hours}");
        }
        else
        {
            Console.WriteLine($"{item.Key}- {item.Value.ToString()}");
        }
    }
}

Выход

ctPoint_0- 0,0799999982118607 25 25
ctPoint_1- 0,0799999982118607 25 30
ctPoint_2- 0,0799999982118607 30 25
pointCount- 3
type- CyclicTemp
cycles- 2
type- Repeat
cycles- 1
duration- 0 0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...