Перейти к содержанию
Fire Monkey от А до Я
  • 0

Маршалинг/ДеМаршалинг в System.JSON


rareMax

Вопрос

Поддерживает ли стандартная библиотека маршалинг/демаршалинг классов? Сейчас работаю с XSuperObject - работа очень приятная с ним. Но огорчает то, что тащит за собой тяжелые библиотеки(Инди, БД). Если нет - может кто знает альтернативы полегче? В идеале будет если так же будут Marshalling Attributes

Ссылка на комментарий

Рекомендуемые сообщения

  • 1

Если я правильно понял, то https://github.com/magicxor/MXUtils/blob/master/Source/MX.MarshalManager.pas

Пример, в котором маршалится/анмаршалится объект типа TList<string>:https://github.com/magicxor/MXUtils/blob/master/Samples/MarshalManager/uFormMain.pas

Ссылка на комментарий
  • 0
7 минут назад, krapotkin сказал:

XSuperObject  - это всего два файла

что куда она тащит??

unit XSuperObject;

interface

uses
  Classes,
  Variants,
  SysUtils,
  Character,
  XSuperJSON,
  RTTI,
  TypInfo,
  {X}DB,
  Generics.Collections,
  {X}IdGlobal,
  {X}IdCoderMIME;

Приходится линковать ИнДи в мой компонент, хотя я инди не использую. Впринципе не очень критично - но все же...

Ссылка на комментарий
  • 0

угу, посмотрел, раньше вроде не было этого

я думаю, это просто лень ему было написать тип PtrInt и еще парочку 

надо написать автору на гитхабе, он быстро исправляет ошибки

Ссылка на комментарий
  • 0

Только есть один нюанс. В классе все свойства должны начинаться с буквы F. Если вы используете  классы с Сеттерами и Геттерами - то проблем быть не должно.

 

Ссылка на комментарий
  • 0
1 час назад, Rusland сказал:

Объясните в двух словах что такое маршалинг/демаршалинг классов?

 

Вот я, например, работаю с ТелеграмБот АПИ. У него есть свои типы данных(если их так можно назвать).

К примеру тип User

Цитата

User

This object represents a Telegram user or bot.

Field Type Description
id Integer Unique identifier for this user or bot
first_name String User‘s or bot’s first name
last_name String Optional. User‘s or bot’s last name
username String Optional. User‘s or bot’s username

Когда вы запрашиваете какую то инфу с участием этого типа вам придет JSON с такими данными(в моем примере getMe):

Цитата

'{"ok":true,"result":{"id":122041176,"first_name":"Delphi in TelegAPI","username":"test_delphi_api_bot"}}'

В "result" будет как раз этот тип "User". Что бы не парсить отдельно каждое поле я создал аналогичный класс в делфи:

TTelegaUser = Class
  private
    FID: Integer;
    FFirstName: String;
    FLastName: String;
    FUsername: String;
  published
    /// <summary>
    /// Unique identifier for this user or bot
    /// </summary>
    /// <returns></returns>
    [ALIAS('id')]
    property ID: Integer read FID write FID;
    /// <summary>
    /// User‘s or bot’s first name
    /// </summary>
    [ALIAS('first_name')]
    property FirstName: String read FFirstName write FFirstName;
    /// <summary>
    /// Optional. User‘s or bot’s last name
    /// </summary>
    [ALIAS('last_name')]
    property LastName: String read FLastName write FLastName;
    /// <summary>
    /// Optional. User‘s or bot’s username
    /// </summary>
    [ALIAS('username')]
    property Username: String read FUsername write FUsername;
  End;

И теперь могу заполнить данными с моего запроса приблизительно так*:

FtelegUser := TTelegaUser.FromJSON(content);

* - На самом деле у меня чуть подругому.

* - При условии что в "content" у вас будет приблизительно такое содержание:

Цитата

{"id":122041176,"first_name":"Delphi in TelegAPI","username":"test_delphi_api_bot"}

 

Изменено пользователем Сысоев Максим
Ссылка на комментарий
  • 1
27 минут назад, krapotkin сказал:

у родной нет таких клевых штук как alias('');

Да, согласен. Но если автор хочет "родными", то выглядит это так:

type
  TTelegaUser = Class
  private
    FID: Integer;
    FFirst_Name: String;
    FLast_Name: String;
    FUsername: String;
  published
    property ID: Integer read FID write FID;
    property First_Name: String read FFirst_Name write FFirst_Name;
    property Last_Name: String read FLast_Name write FLast_Name;
    property Username: String read FUsername write FUsername;
  End;

.....


procedure TForm1.Button1Click(Sender: TObject);
var
  TelegaUser: TTelegaUser;
begin
  TelegaUser := TJson.JsonToObject<TTelegaUser>(MEMO1.Lines.Text);
end;
    
........    

В memo1 лежит ваш JSON

{"id":122041176,"first_name":"Delphi in TelegAPI","username":"test_delphi_api_bot"}

Важно чтобы у класса Свойства назывались точно так-же как в JSON.

Изменено пользователем Andy
Ссылка на комментарий
  • 0

конечно, любые public оно будет тянуть

просто вот у меня как-то нечасто объекты без вложенных внутри списков/массивов

а с этим уже не все так просто

Ссылка на комментарий
  • 0
2 минуты назад, krapotkin сказал:

конечно, любые public оно будет тянуть

просто вот у меня как-то нечасто объекты без вложенных внутри списков/массивов

а с этим уже не все так просто

Я передавал "родными" компонентами и вложенные массивы, и массивы классов - проблем не встретил

 

Ссылка на комментарий
  • 2

Для Syste,.JSON необходимо использовать атрибуты по типу которые расположены в REST.Json.Types

[JSONNameAttribute('НАЗВАНИЕ')] -Так ваша переменная назвается в JSON 

[JSONMarshalledAttribute(False)] - Так блокируется выгрузка (нащет загрузки не уверен) тоесть при TJsonObject(oJSON).ToString переменной с таким атрибутом не будет

TItems = class
  private
    [JSONNameAttribute('ERROR')]
    FERROR: String;
    [JSONNameAttribute('RESULT')]
    FRESULT: String;
    [JSONMarshalledAttribute(False)]
    FOwner : TItems;
  public
    property ERROR  : String read FERROR  write FERROR;
    property RESULT : String read FRESULT write FRESULT;
    property Owner  : TItems read FOwner  write FOwner;
  end;
  
 -------------Результат TJsonObject().ToString---------------------
 {"ERROR": "", "RESULT": ""}
 
 ==================================================================
 
 TItems = class
  private
    FERROR: String;
    FRESULT: String;
    FOwner : TItems;
  public
    property ERROR  : String read FERROR  write FERROR;
    property RESULT : String read FRESULT write FRESULT;
    property Owner  : TItems read FOwner  write FOwner;
  end;
  
 -------------Результат TJsonObject().ToString---------------------
 {"eRROR": "", "rESULT": "", "owner": ""} 

Если честно то не знаю почему так все используют XSuperObject, встроенного инструмента "System.JSON, REST.Json, REST.Json.Types" с головой хватает на всё 

Ссылка на комментарий
  • 0
В 17.01.2018 в 07:55, krapotkin сказал:

XSO удобнее в 10 раз по синтаксису и не требует бесконечных приведений типов.

Может быть. Я обычно чтобы распарсить ответ от сервера, создаю класс и загружаю в него и уже потом работаю с классом (чего не умеет XSuperObject). Ну и как результат я не делаю приведение типов.

Ссылка на комментарий
  • 0

X:=TSuperObject.Create(json);

myObj.AssignFromJSON(X);

ну и загрузка-выгрузка в класс это не совсем работа с JSON

если он заменится на любой другой формат, мы и не узнаем...

Изменено пользователем krapotkin
Ссылка на комментарий
  • 0
  • Модераторы
В 18.01.2018 в 13:08, Виталий Иванов сказал:

Может быть. Я обычно чтобы распарсить ответ от сервера, создаю класс и загружаю в него и уже потом работаю с классом (чего не умеет XSuperObject). Ну и как результат я не делаю приведение типов.

Кто сказал что XSO этого не умеет?

и структуры и классы спокойно преобразовываются в обе стороны

Ссылка на комментарий
  • 0

Столкнулся со странным JSON-текстом.

Цитата

{
		labels: {
			ru: "Все для дома",
			by: "Усё для дома"
		},
		alias: {
			ru: "Для_дома_и_дачи",
			by: "Для_дома_і_дачы"
		},
		value: "3000",
		parent: null
	},

Приходит от сервера в виде javascript.

Обратите внимание, что у названий нет двойных кавычек.

Я так понимаю, что я должен  сделать демаршалинг этого json-текста? Это значит, что я должен знать правильную структуру объекта перед демаршалингом?

Спасибо.

 

Я просто с маршалингом ни разу ещё не сталкивался.

 

Ссылка на комментарий
  • 0

маршалинг и демаршалинг по определению привязаны к типу объекта

RTTI предоставляет список свойств и атрибутов и это все перегоняется в строку, передается по сети и восстанавливается из строки обратно на другом конце

при десериализации поле JSON должно записаться в поле объекта. если такого поля нет, очевидно будет ошибка.

Умеет ли XSO парсить новый JSON - не пробовал.

Ссылка на комментарий

Присоединяйтесь к обсуждению

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

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...