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

BAZAg

Client
Регистрация
08.11.2015
Сообщения
1 760
Благодарностей
2 399
Баллы
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 например отправить данные обратно на сайт и тп.

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

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

Вложения

Для запуска проектов требуется программа ZennoPoster.
Это основное приложение, предназначенное для выполнения автоматизированных шаблонов действий (ботов).
Подробнее...

Для того чтобы запустить шаблон, откройте программу ZennoPoster. Нажмите кнопку «Добавить», и выберите файл проекта, который хотите запустить.
Подробнее о том, где и как выполняется проект.

radv

Client
Регистрация
11.05.2015
Сообщения
3 674
Благодарностей
1 859
Баллы
113
:ay: Почти конкурсная статья
 

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