Lección 19 · 19 de 20
JSON con fpjson · Pascal
Lea y cree JSON en Free Pascal con fpjson y jsonparser: recorra un pedido, sume sus líneas y responda con un objeto JSON nuevo.

La unidad `fpjson` representa el JSON como objetos de Pascal (TJSONObject, TJSONArray, números y textos), y `jsonparser` añade el analizador. `GetJSON` convierte el texto Incoming en ese árbol y devuelve la raíz, que aquí se trata como objeto con as TJSONObject.
Los valores se leen por nombre y tipo: order.Integers['id'], line.Strings['sku'], order.Arrays['lines']. `FindPath('customer.name')` baja por varios niveles de una vez con una ruta separada por puntos. Si un nombre no existe o el tipo no coincide, se lanza una excepción.
El for item in recorre el array de líneas; cada item es un TJSONEnum y su Value es el objeto de la línea. El total se suma en céntimos enteros, que además evita un detalle de fpjson: los números con decimales salen en notación científica al convertirlos a texto.
Para crear JSON, TJSONObject.Create([...]) recibe pares de nombre y valor, y Add añade más, incluso un TJSONArray completo. `AsJSON` lo escribe en una línea (FormatJSON lo escribiría indentado). Cada objeto es dueño de lo que contiene: un solo Free sobre la raíz libera todo el árbol, y los dos try ... finally garantizan que se libere.
Código · main.pas
program main;uses SysUtils, fpjson, jsonparser;const Incoming = '{"id": 1042, "customer": {"name": "Lucia Romero", "city": "Malaga"},' + ' "lines": [{"sku": "MUG-01", "qty": 2, "cents": 850},' + ' {"sku": "TEA-12", "qty": 1, "cents": 1295}]}';var order, line, reply: TJSONObject; item: TJSONEnum; total: Integer = 0;begin order := GetJSON(Incoming) as TJSONObject; // parse the text into objects try WriteLn('Order ', order.Integers['id'], ' for ', order.FindPath('customer.name').AsString); for item in order.Arrays['lines'] do begin line := item.Value as TJSONObject; WriteLn(' ', line.Strings['sku'], ' x', line.Integers['qty']); total := total + line.Integers['qty'] * line.Integers['cents']; end; reply := TJSONObject.Create(['order', order.Integers['id'], 'status', 'confirmed']); try reply.Add('total_cents', total); reply.Add('tags', TJSONArray.Create(['paid', 'gift'])); // reply owns it now WriteLn(reply.AsJSON); finally reply.Free; // frees everything inside too end; finally order.Free; end;end.Salida · fpc main.pas && ./main
Order 1042 for Lucia Romero
MUG-01 x2
TEA-12 x1
{ "order" : 1042, "status" : "confirmed", "total_cents" : 2995, "tags" : ["paid", "gift"] }Para recordar
GetJSONconvierte un texto en un árbol de objetos JSON.Integers[...],Strings[...]yArrays[...]leen por nombre y tipo.FindPath('a.b')baja por varios niveles a la vez.TJSONObject.Create([...])yAddconstruyen JSON;AsJSONlo escribe.- Liberar la raíz libera todo lo que contiene.
Ejercicio
Añada a la respuesta un objeto shipping con la ciudad del cliente (order.FindPath('customer.city').AsString) y un campo express a True.