struct JSON* is an opaque handle over one node. json_new gives you an empty * one, json_parse fills it from text, json_delete frees the tree — child nodes * from array_element/object_element belong to that tree and must NOT be deleted * individually. json_get_string hands back a copy you free(). * * The important discipline: check the type before you read it. Calling * json_get_int on a stri
| 781 | * (is_valid → is_object → object_contains → is_<type>) are not optional |
| 782 | * politeness, they are how a malformed server reply stays survivable. */ |
| 783 | void section_json(void) |
| 784 | { |
| 785 | /* One literal: picoc does not concatenate adjacent string literals. */ |
| 786 | char* doc = "{\"name\":\"Checkpoint\",\"version\":5,\"beta\":true,\"tags\":[\"saves\",\"scripts\"],\"author\":{\"handle\":\"FlagBrew\"}}"; |
| 787 | struct JSON* root; |
| 788 | struct JSON* node; |
| 789 | struct JSON* child; |
| 790 | char* s; |
| 791 | int i; |
| 792 | |
| 793 | root = json_new(); |
| 794 | json_parse(root, doc); |
| 795 | |
| 796 | if (!json_is_valid(root) || !json_is_object(root)) { |
| 797 | json_delete(root); |
| 798 | gui_message("json_parse rejected the document."); |
| 799 | return; |
| 800 | } |
| 801 | |
| 802 | /* strings */ |
| 803 | if (json_object_contains(root, "name")) { |
| 804 | node = json_object_element(root, "name"); |
| 805 | if (json_is_string(node)) { |
| 806 | s = json_get_string(node); |
| 807 | printf("name: %s\n", s); |
| 808 | free(s); |
| 809 | } |
| 810 | } |
| 811 | |
| 812 | /* numbers and booleans */ |
| 813 | node = json_object_element(root, "version"); |
| 814 | if (json_is_int(node)) { |
| 815 | printf("version: %d\n", json_get_int(node)); |
| 816 | } |
| 817 | node = json_object_element(root, "beta"); |
| 818 | if (json_is_bool(node)) { |
| 819 | printf("beta: %d\n", json_get_bool(node)); |
| 820 | } |
| 821 | |
| 822 | /* arrays */ |
| 823 | node = json_object_element(root, "tags"); |
| 824 | if (json_is_array(node)) { |
| 825 | printf("tags (%d):\n", json_array_size(node)); |
| 826 | for (i = 0; i < json_array_size(node); i++) { |
| 827 | child = json_array_element(node, i); |
| 828 | if (json_is_string(child)) { |
| 829 | s = json_get_string(child); |
| 830 | printf(" %s\n", s); |
| 831 | free(s); |
| 832 | } |
| 833 | } |
| 834 | } |
| 835 | |
| 836 | /* nested objects, and walking keys by index when you do not know them */ |
| 837 | node = json_object_element(root, "author"); |
| 838 | if (json_is_object(node)) { |
| 839 | s = json_object_key(node, 0); |
| 840 | printf("author key 0: %s\n", s); |