Показываю как я работаю с JSON

  • Автор темы Автор темы BAZAg
  • Дата начала Дата начала
  • Теги Теги
    json

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 915
Реакции
2 666
Баллы
113
Иногда бывает так, что мы получаем данные с каких-то сайтов примерно в таком виде:
JSON:
Развернуть Свернуть Копировать
{"field_0":"","field_1":0,"field_2":0,"field_3":0,"field_4":0,"field_5":0}
JSON:
Развернуть Свернуть Копировать
[{"field_0":"ob_0","field_1":0,"field_2":0,"field_3":0,"field_4":0,"field_5":0},{"field_0":"ob_1","field_1":0,"field_2":0,"field_3":0,"field_4":0,"field_5":0}]
И вот, не многие знают как можно работать с этими данными так, чтобы это было более-менее удобно.
Не хочу сказать что это самый правильный вариант, но в целом хочу поделиться концепцией, к которой изучая зенно, шарп и автоматизацию в целом.

Для того, чтобы не отталкиваться от какого-то сайта, набросал в общем коде методы, которые должны сгенерировать мне эти демо-данные.

C#:
Развернуть Свернуть Копировать
public static string GetData1(){ // Занимается созданием json из объекта
    object ob = new{
        field_0 = "",
        field_1 = 0,
        field_2 = 0,
        field_3 = 0,
        field_4 = 0,
        field_5 = 0,
        };
    return GetJson(ob);
}

public static string GetData2(){ // Занимается созданием json из массива/списка объектов
    List<object> list = new List<object>();
    for(int i=0;i<2;i++){
        list.Add(new{
            field_0 = string.Format("ob_{0}",i),
            field_1 = 0,
            field_2 = 0,
            field_3 = 0,
            field_4 = 0,
            field_5 = 0,
            });
    }
    return GetJson(list);
}

public static string GetJson(object data){ // Занимается превращением объекта в Json строку
    return Global.ZennoLab.Json.JsonConvert.SerializeObject(data);
}

И вот, после вызова данных методов используя код ниже - получил те же две строки json, которые указывал в начале.
Пример вызова:
Развернуть Свернуть Копировать
string json1 = CommonCode.GetData1(); // Имитация GET объект
project.SendInfoToLog(json1);
string json2 = CommonCode.GetData2(); // Имитация GET список объектов
project.SendInfoToLog(json2);

Дальше, мне показалось что писать project.SendInfoToLog не очень удобно (получается, если я захочу вызвать уведомление в лог в общем коде - придётся таскать с собой IZennoPosterProjectModel во все методы. Решил я найти какое-то решение, чтобы просто писать например Log("mess") - что позволило бы мне пробросить данные, и чтобы они отправились в лог.

C#:
Развернуть Свернуть Копировать
public static Action<object> OnLog { set { Log = value; } }
public static Action<object> Log;

И в результате код, который был изначально выше преобразился в такой:
C#:
Развернуть Свернуть Копировать
CommonCode.OnLog = (object s) => project.SendInfoToLog(s.ToString()); // Пробрасываю обработчик

string json1 = CommonCode.GetData1(); // Имитация GET объект
CommonCode.Log(json1);
string json2 = CommonCode.GetData2(); // Имитация GET список объектов
CommonCode.Log(json2);

Так вот, создать объект, превратить его в строку json и вывести в лог (чтобы посмотреть что получилось) - из демонстрации выше думаю должно быть понятно.
А дальше - нужно понять как вообще получить с этого хоть какую-то пользу.
Вручную писать код можно, и иногда без этого совсем никак, но в случае с данными json строками можно поступить чуток по другому.
Идём на сайты https://jsonutils.com/ или https://json2csharp.com/ вводим данный код, и получаем готовые классы, которые можем добавить в общий код. Получится что-то вроде этого:

C#:
Развернуть Свернуть Копировать
public class MyObject {
    public string field_0 { get; set; }           
    public int field_1 { get; set; }
    public int field_2 { get; set; }
    public int field_3 { get; set; }
    public int field_4 { get; set; }
    public int field_5 { get; set; }   
}

Дальше создаю в общем коде 2 метода, которые собственно будут использовать данный объект:
C#:
Развернуть Свернуть Копировать
public static string GetData3(){
            MyObject ob = new MyObject();
            return GetJson(ob);
        }
        public static string GetData4(){
            List<object> list = new List<object>();
            for(int i=0;i<2;i++){
            list.Add(new MyObject(){
                field_0 = string.Format("ob_{0}",i),
                field_1 = 0,
                field_2 = 0,
                field_3 = 0,
                field_4 = 0,
                field_5 = 0
            });
            }
            return GetJson(list);
        }

Вызываю данные методы с кубика:
C#:
Развернуть Свернуть Копировать
string json3 = CommonCode.GetData3(); // Имитация GET список объектов
CommonCode.Log(json3);
string json4 = CommonCode.GetData4(); // Имитация GET список объектов
CommonCode.Log(json4);

И всё бы ничего, но по умолчанию оказывается что строка получает значение null, а не string.Empty.
JSON:
Развернуть Свернуть Копировать
{"field_0":null,"field_1":0,"field_2":0,"field_3":0,"field_4":0,"field_5":0}
Чтобы такое не происходило - для этого класса необходимо прописать конструктор, который будет вызываться при создании объекта.
Добавляю в класс код:
C#:
Развернуть Свернуть Копировать
public MyObject(){
    field_0 = string.Empty;
    field_1=0;
    field_2=0;
    field_3=0;
    field_4=0;
    field_5=0;
}
После этого проблема с null решена (заменяется на указанное в конструкторе значение).

В этом коде мне ещё не нравится, что к полям объекта, если вдруг нужно будет их изменять - придётся обращаться как-то ob.field_0, что как-бы не красиво совсем - то что нам в json нужны именно такие поля совсем не значит, что мы должны так мучить себя и запоминать как именно они там называются.
Для того, чтобы исправить ситуацию - нужно изменить чуток созданный класс, указав атрибуты.
В итоге класс получает примерно такой вид (и класс уже будет MyObject2 чтобы не изменять предыдущие методы, а методов я допишу ещё 2 штуки уже с указанием этого класса):
C#:
Развернуть Свернуть Копировать
public class MyObject2 {
    [Global.ZennoLab.Json.JsonPropertyAttribute("field_0")]
    public string F1 { get; set; }           
    [Global.ZennoLab.Json.JsonPropertyAttribute("field_1")]
    public int F2 { get; set; }
    [Global.ZennoLab.Json.JsonPropertyAttribute("field_2")]
    public int F3 { get; set; }
    [Global.ZennoLab.Json.JsonPropertyAttribute("field_3")]
    public int F4 { get; set; }
    [Global.ZennoLab.Json.JsonPropertyAttribute("field_4")]
    public int F5 { get; set; }
    [Global.ZennoLab.Json.JsonPropertyAttribute("field_5")]
    public int F6 { get; set; }   

    public MyObject2 (){
        F1 = string.Empty;
        F2 = 0;
        F3 = 0;
        F4 = 0;
        F5 = 0;
        F6 = 0;           
    }
}
C#:
Развернуть Свернуть Копировать
public static string GetData5(){
    MyObject2 ob = new MyObject2();
    return GetJson(ob);
}
public static string GetData6(){
    List<object> list = new List<object>();
    for(int i=0;i<2;i++){
        list.Add(new MyObject2(){
            F1 = string.Format("ob_{0}",i),
            F2 = 0,
            F3 = 0,
            F4 = 0,
            F5 = 0,
            F6 = 0           
            });
    }
    return GetJson(list);
}
Вызываю для вывода в лог. По факту ничего не изменилось :)
C#:
Развернуть Свернуть Копировать
string json5 = CommonCode.GetData5(); // Имитация GET список объектов
CommonCode.Log(json5);
string json6 = CommonCode.GetData6(); // Имитация GET список объектов
CommonCode.Log(json6);

Осталось теперь с полученной JSON-строки получить объект и массив/список объектов.
Для этого в общий код бросаю ещё один метод, который будет выполнять эту работу:
C#:
Развернуть Свернуть Копировать
public static T GetObject<T> (string json){   
    using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(json))){
        if (stream == null || stream.CanRead == false) return default(T);
        using (var sr = new StreamReader(stream)){
            using (var jtr = new Global.ZennoLab.Json.JsonTextReader(sr)) {
                return Global.ZennoLab.Json.JsonSerializer.Create().Deserialize<T>(jtr);
            }
        }
    }
}

Посмотреть на объекты в логе мы не сможем, но мы сможем например посмотреть какое-то поле, например F1 у этого объекта.
Собственно сам пример вызова:
C#:
Развернуть Свернуть Копировать
string json5 = CommonCode.GetData5(); // Имитация GET список объектов
CommonCode.Log(json5);
MyObject2 item = CommonCode.GetObject<MyObject2>(json5);
CommonCode.Log(item.F1);

string json6 = CommonCode.GetData6(); // Имитация GET список объектов
CommonCode.Log(json6);
List<MyObject2> items = CommonCode.GetObject<List<MyObject2>>(json6);
items.ForEach(x=>CommonCode.Log(x.F1)); // вывожу в лог

Естественно, что вместо вывода в лог мы можем например таким образом провести какие-то другие манипуляции, и потом вернув обратно в JSON например отправить данные обратно на сайт и тп.

Пример всего что здесь написал добавлю в виде шаблона.
Есть что добавить по теме - пиши ниже :)
И да, перенесите пожалуйста тему в правильный раздел.

Если узнал для себя что-то новое - можешь ткнуть "Спасибо".
 

Вложения

:ay: Почти конкурсная статья
 

Кто просматривает тему: (Всего: 0, Пользователи: 0, Гости: 0)