Тема: JSON -> TDataSet
Доброго часу доби!
Цікавить наступне питання: як стандартними засобами Delphi(XE3 і вище) розпарсити JSON-відповідь від сервера і передати її у TDataSet. І чи взагалі, таке існує?
Ви не увійшли. Будь ласка, увійдіть або зареєструйтесь.
Ласкаво просимо вас на україномовний форум з програмування, веб-дизайну, SEO та всього пов'язаного з інтернетом та комп'ютерами.
Будемо вдячні, якщо ви поділитись посиланням на Replace.org.ua на інших ресурсах.
Для того щоб створювати теми та надсилати повідомлення вам потрібно Зареєструватись.
Український форум програмістів → Pascal/Delphi → JSON -> TDataSet
Для відправлення відповіді ви повинні увійти або зареєструватися
Доброго часу доби!
Цікавить наступне питання: як стандартними засобами Delphi(XE3 і вище) розпарсити JSON-відповідь від сервера і передати її у TDataSet. І чи взагалі, таке існує?
Тут усе досить складно, бо JSON-об'єкт є багатовимірним, а датасет - це двовимірна структура. Хоча звичайно існують вкладені датасети та TDataSetField.
Плюс немає ніяких стандартів на формат JSON-об'єктів, тому одразу ж виникає проблема з парсингом.
Найпростіший варіант вирішення цієї проблеми, це ручний парсинг + InMemory-датасет. Для парсингу є стандартні класи у DBXJSON, або сторонні типу SuperObject. У якості датасету у пам'яті можна використати TClientDataSet або більш гнучкий TjvMemoryData.
Якщо використання пам'яті є проблемою, то можна спробувати застосувати TAdapterBindSource. Він дозволить парсити JSON-об'єкти динамічно, коли в цьому виникає потреба.
Також якісь можливості автоматичної прив'язки до JSON є у DataSnap, але я про них майже нічого не чув.
Ну й нарешті REST Library. Ця бібліотека з'явилася щойно у XE5 і призначена для взаємодії з різними веб-сервісами. Вона містить у своєму складі TRESTResponseDataSetAdapter.
Я б радив вам подивитися у першу чергу в сторону REST Library. У XE6 ця бібліотека буде розширена готовими класами для взаємодії з популярними сервісами типу Google Drive.
Добавлю:
в Delphi XE2+ є компонент для роботи з JSON, але веб-сервіси часто поршують стандарт (походу на javascript це неважливо). В мене є правлений модуль, який працює із неправльними JSON-масивами.
можу скинути (якщо ще не загубив його)
Здається це)
Просто кинь у папку з проектом і в uses допиши Data.DBXJSON2 замість Data.DBXJSON, а далі працюєш так само як з оригіналом.
(це для Delphi XE2+ походу)
Можливо я ще якісь хелпери писав... не пам'ятаю)
То внизу треба було два рази нажати...
class function TJSONObject.ParsePair(const Br: TJSONByteReader; const Parent: TJSONObject): Integer;
var
Pair: TJSONPair;
CommaPos: Integer;
begin
Pair := TJSONPair.Create;
Parent.AddDescendant(Pair);
// CommaPos := ParseString(Br, Pair); /////////////////////////////////////////
{ Заміна щоб бачило рядки типу {33:33}
ConsumeWhitespaces(Br);
if Br.PeekByte in [Ord('0')..Ord('9')] then
CommaPos := ParseNumber(Br, Pair)
else
CommaPos := ParseString(Br, Pair);
{/}
if CommaPos > 0 then
begin
ConsumeWhitespaces(Br);
if Br.Empty then
Exit(-Br.Offset);
if Br.PeekByte <> Ord(':') then
Exit(-Br.Offset);
Br.ConsumeByte;
ConsumeWhitespaces(Br);
CommaPos := ParseValue(Br, Pair);
end;
Result := CommaPos;
end;
ADR
Мабуть варто це на QC запостити.
Добавив)
http://qc.embarcadero.com/wc/qcmain.aspx?d=122716
(сильно коряво написав по англ?)
це хіба не помилка?О_о
procedure TRect.SetWidth(const Value: Integer);
begin
Self.Right := Self.Left + Value;
end;
тобто якщо задати ширину в одиничку то вона вона буде двійкою (типу 0 і 1)
боюсь вручну міняти, щоб щось не поламати) System.Types системний розділ як не як...
А хіба Self.Left не від 0 рахується?
в цьому ж і проблема...
коли:
Left := 0
Width := 1
то
Rigth = 1, а має бути нуль.
Chemist-i написав:А хіба Self.Left не від 0 рахується?
в цьому ж і проблема...
коли:
Left := 0
Width := 1
то
Rigth = 1, а має бути нуль.
чому це має бути 0? має бути 1. right показує в координатах праву точку, т.е. ліва плюсь ширина, (ширина теж може бути 0)
ADR написав:Chemist-i написав:А хіба Self.Left не від 0 рахується?
в цьому ж і проблема...
коли:
Left := 0
Width := 1
то
Rigth = 1, а має бути нуль.чому це має бути 0? має бути 1. right показує в координатах праву точку, т.е. ліва плюсь ширина, (ширина теж може бути 0)
просто якщо у мене є картинка із Left=0, Rigth=1 то я хотів щоб у Width було 2...
Ви можете руками додати там де Вам треба. Але коли Left=0, Rigth=1 самі подумайте. ящо зменшити Rigth на одинию, що відбудеться? І Ви хочете сказати, що при Left=0, Rigth=0 ширина буде дорівнювати 1-ці? це не правильно.
Добавив)
http://qc.embarcadero.com/wc/qcmain.aspx?d=122716
(сильно коряво написав по англ?)
Варто іще додати які саме сервіси видають json у такому некоректному форматі.
це хіба не помилка?О_о
procedure TRect.SetWidth(const Value: Integer); begin Self.Right := Self.Left + Value; end;
тобто якщо задати ширину в одиничку то вона вона буде двійкою (типу 0 і 1)
А існує якийсь стандарт?
Ви можете руками додати там де Вам треба. Але коли Left=0, Rigth=1 самі подумайте. ящо зменшити Rigth на одинию, що відбудеться? І Ви хочете сказати, що при Left=0, Rigth=0 ширина буде дорівнювати 1-ці? це не правильно.
але якщо ми маємо картинку шириною в одну точку то ширина має бути 1, а не нуль...
та вручну я вже зробив...
зараз фігньою страдаю. пишу прогу щоб різати скани на яких є декілька фоток розділених білим. роблю рекурсивним поділом картинки на два, доки є прям, білі, лінії. але зараз є проблема із швидкодією)
(ПС я картинку на пряму не ріжу, тільки зберігаю параметри обрізу в TRect)
Варто іще додати які саме сервіси видають json у такому некоректному форматі.
треба фейсбук прошарити. VK їм не цікаво...
А існує якийсь стандарт?
навіть не знаю... ну коли я питаю Width у якогось графічного компонента то він мені вертає кількість пікселів...
ADR
О, подібним займався нещодавно, отримував доступ до пікселів bmp-шок спочатку
Але це вже офтоп.
ADR
О, подібним займався нещодавно, отримував доступ до пікселів bmp-шок спочатку▼через ScanLine▼А потім написав взагалі функцію доставання з bmp адрес тих пікселівАле це вже офтоп.
В мене якраз у цьому і була проблема, але я її вирішив до того як прочитав пост(
просто копіюю вміст зображення через TBitmapData.GetPixel в масив, бо GetPixel викликається з бібліотеки, а це дуже довго.
все одно зображення 3500*2500 не піднімає... дам меншу задачу і подивлюсь профілінг (чи як там його звати)
знайшов головну помилку: зробив надто чутливі налаштування і прога поринула у рекурсію (щоб кожну точку окремо взяти))
зараз ніби працює
Для відправлення відповіді ви повинні увійти або зареєструватися