DMarlon Studio

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.

Pascal · JSON con fpjson en DMarlon Studio: el código del ejemplo y su salida en la terminal

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

  • GetJSON convierte un texto en un árbol de objetos JSON.
  • Integers[...], Strings[...] y Arrays[...] leen por nombre y tipo.
  • FindPath('a.b') baja por varios niveles a la vez.
  • TJSONObject.Create([...]) y Add construyen JSON; AsJSON lo 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.