37
38:- module(json,
39 [ json_read/2, 40 json_read/3, 41 atom_json_term/3, 42 json_write/2, 43 json_write/3, 44 is_json_term/1, 45 is_json_term/2, 46 47 json_read_dict/2, 48 json_read_dict/3, 49 json_write_dict/2, 50 json_write_dict/3, 51 atom_json_dict/3, 52 json/4 53 ]). 54:- use_module(library(record)). 55:- use_module(library(error)). 56:- use_module(library(option)). 57:- use_module(library(lists)). 58:- use_module(library(apply)). 59:- use_module(library(quasi_quotations)). 60
61:- use_foreign_library(foreign(json)). 62
63:- multifile
64 json_write_hook/4, 65 json_dict_pairs/2. 66
67:- predicate_options(json_read/3, 3,
68 [ null(ground),
69 true(ground),
70 false(ground),
71 end_of_file(ground),
72 value_string_as(oneof([atom,string])),
73 qqdict(list(compound(=(atom,var))))
74 ]). 75:- predicate_options(json_write/3, 3,
76 [ indent(nonneg),
77 step(positive_integer),
78 tab(positive_integer),
79 width(nonneg),
80 null(ground),
81 true(ground),
82 false(ground),
83 serialize_unknown(boolean)
84 ]). 85:- predicate_options(json_read_dict/3, 3,
86 [ tag(atom),
87 default_tag(atom),
88 pass_to(json_read/3, 3)
89 ]). 90:- predicate_options(json_write_dict/3, 3,
91 [ tag(atom),
92 pass_to(json_write/3, 3)
93 ]). 94:- predicate_options(is_json_term/2, 2,
95 [ null(ground),
96 true(ground),
97 false(ground)
98 ]). 99:- predicate_options(atom_json_term/3, 3,
100 [ as(oneof([atom,string,codes])),
101 pass_to(json_read/3, 3),
102 pass_to(json_write/3, 3)
103 ]). 104
128
129:- record json_options(
130 null:ground = @(null),
131 true:ground = @(true),
132 false:ground = @(false),
133 end_of_file:ground = error,
134 value_string_as:oneof([atom,string]) = atom,
135 tag:atom = '',
136 default_tag:(var;atom) = '#',
137 qqdict:list(compound(atom=var))). 138
139default_json_dict_options(
140 json_options(null, true, false, error, string, '', #, _)).
141
142
143 146
155
156atom_json_term(Atom, Term, Options) :-
157 ground(Atom),
158 !,
159 setup_call_cleanup(
160 open_string(Atom, In),
161 json_read(In, Term, Options),
162 close(In)).
163atom_json_term(Result, Term, Options) :-
164 select_option(as(Type), Options, Options1, atom),
165 ( type_term(Type, Result, Out)
166 -> true
167 ; must_be(oneof([atom,string,codes,chars]), Type)
168 ),
169 with_output_to(Out,
170 json_write(current_output, Term, Options1)).
171
172type_term(atom, Result, atom(Result)).
173type_term(string, Result, string(Result)).
174type_term(codes, Result, codes(Result)).
175type_term(chars, Result, chars(Result)).
176
177
178 181
254
255json_read(Stream, Term) :-
256 default_json_options(Options),
257 ( json_value_top(Stream, Term, Options)
258 -> true
259 ; syntax_error(illegal_json, Stream)
260 ).
261json_read(Stream, Term, Options) :-
262 make_json_options(Options, OptionTerm, _RestOptions),
263 ( json_value_top(Stream, Term, OptionTerm)
264 -> true
265 ; syntax_error(illegal_json, Stream)
266 ).
267
268json_value_top(Stream, Term, Options) :-
269 stream_property(Stream, type(binary)),
270 !,
271 setup_call_cleanup(
272 set_stream(Stream, encoding(utf8)),
273 json_value_top_(Stream, Term, Options),
274 set_stream(Stream, type(binary))).
275json_value_top(Stream, Term, Options) :-
276 json_value_top_(Stream, Term, Options).
277
278json_value_top_(Stream, Term, Options) :-
279 get_code(Stream, C0),
280 ws(C0, Stream, C1),
281 ( C1 == -1
282 -> json_options_end_of_file(Options, Action),
283 ( Action == error
284 -> syntax_error(unexpected_end_of_file, Stream)
285 ; Term = Action
286 )
287 ; json_term_top(C1, Stream, Term, Options)
288 ).
289
290json_value(Stream, Term, Next, Options) :-
291 get_code(Stream, C0),
292 ws(C0, Stream, C1),
293 ( C1 == -1
294 -> syntax_error(unexpected_end_of_file, Stream)
295 ; json_term(C1, Stream, Term, Next, Options)
296 ).
297
298json_term(C0, Stream, JSON, Next, Options) :-
299 json_term_top(C0, Stream, JSON, Options),
300 get_code(Stream, Next).
301
302json_term_top(0'{, Stream, json(Pairs), Options) :-
303 !,
304 ws(Stream, C),
305 json_pairs(C, Stream, Pairs, Options).
306json_term_top(0'[, Stream, Array, Options) :-
307 !,
308 ws(Stream, C),
309 json_array(C, Stream, Array, Options).
310json_term_top(0'", Stream, String, Options) :-
311 !,
312 get_code(Stream, C1),
313 json_string_codes(C1, Stream, Codes),
314 json_options_value_string_as(Options, Type),
315 codes_to_type(Type, Codes, String).
316json_term_top(0'-, Stream, Number, _Options) :-
317 !,
318 json_read_number(Stream, 0'-, Number).
319json_term_top(D, Stream, Number, _Options) :-
320 between(0'0, 0'9, D),
321 !,
322 json_read_number(Stream, D, Number).
323json_term_top(C, Stream, Constant, Options) :-
324 json_read_constant(C, Stream, ID),
325 !,
326 json_constant(ID, Constant, Options).
327json_term_top(C, Stream, Var, Options) :-
328 code_type(C, prolog_var_start),
329 json_options_qqdict(Options, QQDict),
330 nonvar(QQDict),
331 !,
332 json_read_var_cont(Stream, Codes),
333 atom_codes(Name, [C | Codes]),
334 ( memberchk(Name=Var, QQDict)
335 -> true
336 ; syntax_error(non_existing_var(Name, QQDict), Stream)
337 ).
338
339json_read_var_cont(Stream, [C | L]) :-
340 peek_code(Stream, C),
341 code_type(C, prolog_identifier_continue),
342 !,
343 get_code(Stream, C),
344 json_read_var_cont(Stream, L).
345json_read_var_cont(_, []).
346
347
348json_pairs(0'}, _, [], _) :- !.
349json_pairs(C0, Stream, [Pair|Tail], Options) :-
350 json_pair(C0, Stream, Pair, C, Options),
351 ws(C, Stream, Next),
352 ( Next == 0',
353 -> ws(Stream, C2),
354 json_pairs(C2, Stream, Tail, Options)
355 ; Next == 0'}
356 -> Tail = []
357 ; syntax_error(illegal_object, Stream)
358 ).
359
360json_pair(C0, Stream, Name=Value, Next, Options) :-
361 json_string_as_atom(C0, Stream, Name),
362 ws(Stream, C),
363 C == 0':,
364 json_value(Stream, Value, Next, Options).
365
366
367json_array(0'], _, [], _) :- !.
368json_array(C0, Stream, [Value|Tail], Options) :-
369 json_term(C0, Stream, Value, C, Options),
370 ws(C, Stream, Next),
371 ( Next == 0',
372 -> ws(Stream, C1),
373 json_array(C1, Stream, Tail, Options)
374 ; Next == 0']
375 -> Tail = []
376 ; syntax_error(illegal_array, Stream)
377 ).
378
379codes_to_type(atom, Codes, Atom) :-
380 atom_codes(Atom, Codes).
381codes_to_type(string, Codes, Atom) :-
382 string_codes(Atom, Codes).
383codes_to_type(codes, Codes, Codes).
384
385json_string_as_atom(0'", Stream, Atom) :-
386 get_code(Stream, C1),
387 json_string_codes(C1, Stream, Codes),
388 atom_codes(Atom, Codes).
389
390json_string_codes(0'", _, []) :- !.
391json_string_codes(0'\\, Stream, [H|T]) :-
392 !,
393 get_code(Stream, C0),
394 ( escape(C0, Stream, H)
395 -> true
396 ; syntax_error(illegal_string_escape, Stream)
397 ),
398 get_code(Stream, C1),
399 json_string_codes(C1, Stream, T).
400json_string_codes(-1, Stream, _) :-
401 !,
402 syntax_error(eof_in_string, Stream).
403json_string_codes(C, Stream, [C|T]) :-
404 get_code(Stream, C1),
405 json_string_codes(C1, Stream, T).
406
407escape(0'", _, 0'") :- !.
408escape(0'\\, _, 0'\\) :- !.
409escape(0'/, _, 0'/) :- !.
410escape(0'b, _, 0'\b) :- !.
411escape(0'f, _, 0'\f) :- !.
412escape(0'n, _, 0'\n) :- !.
413escape(0'r, _, 0'\r) :- !.
414escape(0't, _, 0'\t) :- !.
415escape(0'u, Stream, C) :-
416 get_XXXX(Stream, H),
417 ( hi_surrogate(H)
418 -> get_surrogate_tail(Stream, H, C)
419 ; C = H
420 ).
421
422get_XXXX(Stream, C) :-
423 get_xdigit(Stream, D1),
424 get_xdigit(Stream, D2),
425 get_xdigit(Stream, D3),
426 get_xdigit(Stream, D4),
427 C is D1<<12+D2<<8+D3<<4+D4.
428
429get_xdigit(Stream, D) :-
430 get_code(Stream, C),
431 code_type(C, xdigit(D)),
432 !.
433get_xdigit(Stream, _) :-
434 syntax_error(hexdigit_expected, Stream).
435
436get_surrogate_tail(Stream, Hi, Codepoint) :-
437 ( get_code(Stream, 0'\\),
438 get_code(Stream, 0'u),
439 get_XXXX(Stream, Lo),
440 surrogate([Hi, Lo], Codepoint)
441 -> true
442 ; syntax_error(illegal_surrogate_pair, Stream)
443 ).
444
445
446hi_surrogate(C) :-
447 C >= 0xD800, C < 0xDC00.
448
449lo_surrogate(C) :-
450 C >= 0xDC00, C < 0xE000.
451
452surrogate([Hi, Lo], Codepoint) :-
453 hi_surrogate(Hi),
454 lo_surrogate(Lo),
455 Codepoint is (Hi - 0xD800) * 0x400 + (Lo - 0xDC00) + 0x10000.
456
457json_read_constant(0't, Stream, true) :-
458 !,
459 must_see(`rue`, Stream, true).
460json_read_constant(0'f, Stream, false) :-
461 !,
462 must_see(`alse`, Stream, false).
463json_read_constant(0'n, Stream, null) :-
464 !,
465 must_see(`ull`, Stream, null).
466
467must_see([], _Stream, _).
468must_see([H|T], Stream, Name) :-
469 get_code(Stream, C),
470 ( C == H
471 -> true
472 ; syntax_error(json_expected(Name), Stream)
473 ),
474 must_see(T, Stream, Name).
475
476json_constant(true, Constant, Options) :-
477 !,
478 json_options_true(Options, Constant).
479json_constant(false, Constant, Options) :-
480 !,
481 json_options_false(Options, Constant).
482json_constant(null, Constant, Options) :-
483 !,
484 json_options_null(Options, Constant).
485
491
492ws(Stream, Next) :-
493 get_code(Stream, C0),
494 json_skip_ws(Stream, C0, Next).
495
496ws(C0, Stream, Next) :-
497 json_skip_ws(Stream, C0, Next).
498
499syntax_error(Message, Stream) :-
500 stream_error_context(Stream, Context),
501 throw(error(syntax_error(json(Message)), Context)).
502
503stream_error_context(Stream, stream(Stream, Line, LinePos, CharNo)) :-
504 stream_pair(Stream, Read, _),
505 character_count(Read, CharNo),
506 line_position(Read, LinePos),
507 line_count(Read, Line).
508
509
510 513
518
520
526
528
595
612
617
618:- record json_write_state(indent:nonneg = 0,
619 step:positive_integer = 2,
620 tab:positive_integer = 8,
621 width:nonneg = 72,
622 serialize_unknown:boolean = false
623 ). 624
625json_write(Stream, Term) :-
626 json_write(Stream, Term, []).
627json_write(Stream, Term, Options) :-
628 make_json_write_state(Options, State, Options1),
629 make_json_options(Options1, OptionTerm, _RestOptions),
630 json_write_term(Term, Stream, State, OptionTerm).
631
632json_write_term(Var, _, _, _) :-
633 var(Var),
634 !,
635 instantiation_error(Var).
636json_write_term(json(Pairs), Stream, State, Options) :-
637 !,
638 json_write_object(Pairs, Stream, State, Options).
639json_write_term(Dict, Stream, State, Options) :-
640 is_dict(Dict, Tag),
641 !,
642 json_pairs(Dict, Pairs0),
643 ( nonvar(Tag),
644 json_options_tag(Options, Name),
645 Name \== ''
646 -> Pairs = [Name-Tag|Pairs0]
647 ; Pairs = Pairs0
648 ),
649 json_write_object(Pairs, Stream, State, Options).
650json_write_term(List, Stream, State, Options) :-
651 is_list(List),
652 !,
653 space_if_not_at_left_margin(Stream, State),
654 write(Stream, '['),
655 ( json_write_state_width(State, Width),
656 ( Width == 0
657 -> true
658 ; json_write_state_indent(State, Indent),
659 json_print_length(List, Options, Width, Indent, _)
660 )
661 -> set_width_of_json_write_state(0, State, State2),
662 write_array_hor(List, Stream, State2, Options),
663 write(Stream, ']')
664 ; step_indent(State, State2),
665 write_array_ver(List, Stream, State2, Options),
666 indent(Stream, State),
667 write(Stream, ']')
668 ).
669
670json_write_term(Term, Stream, State, Options) :-
671 json_write_hook(Term, Stream, State, Options),
672 !.
673json_write_term(Number, Stream, _State, _Options) :-
674 number(Number),
675 !,
676 ( float(Number)
677 -> write(Stream, Number)
678 ; integer(Number)
679 -> write(Stream, Number)
680 ; Float is float(Number) 681 -> write(Stream, Float)
682 ).
683json_write_term(True, Stream, _State, Options) :-
684 json_options_true(Options, True),
685 !,
686 write(Stream, true).
687json_write_term(False, Stream, _State, Options) :-
688 json_options_false(Options, False),
689 !,
690 write(Stream, false).
691json_write_term(Null, Stream, _State, Options) :-
692 json_options_null(Options, Null),
693 !,
694 write(Stream, null).
695json_write_term(#(Text), Stream, _State, _Options) :-
696 !,
697 ( ( atom(Text)
698 ; string(Text)
699 )
700 -> json_write_string(Stream, Text)
701 ; term_string(Text, String),
702 json_write_string(Stream, String)
703 ).
704json_write_term(String, Stream, _State, _Options) :-
705 atom(String),
706 !,
707 json_write_string(Stream, String).
708json_write_term(String, Stream, _State, _Options) :-
709 string(String),
710 !,
711 json_write_string(Stream, String).
712json_write_term(AnyTerm, Stream, State, _Options) :-
713 ( json_write_state_serialize_unknown(State, true)
714 -> term_string(AnyTerm, String),
715 json_write_string(Stream, String)
716 ; type_error(json_term, AnyTerm)
717 ).
718
719json_pairs(Dict, Pairs) :-
720 json_dict_pairs(Dict, Pairs),
721 !.
722json_pairs(Dict, Pairs) :-
723 dict_pairs(Dict, _, Pairs).
724
725json_write_object(Pairs, Stream, State, Options) :-
726 space_if_not_at_left_margin(Stream, State),
727 write(Stream, '{'),
728 ( json_write_state_width(State, Width),
729 ( Width == 0
730 -> true
731 ; json_write_state_indent(State, Indent),
732 json_print_length(json(Pairs), Options, Width, Indent, _)
733 )
734 -> set_width_of_json_write_state(0, State, State2),
735 write_pairs_hor(Pairs, Stream, State2, Options),
736 write(Stream, '}')
737 ; step_indent(State, State2),
738 write_pairs_ver(Pairs, Stream, State2, Options),
739 indent(Stream, State),
740 write(Stream, '}')
741 ).
742
743
744write_pairs_hor([], _, _, _).
745write_pairs_hor([H|T], Stream, State, Options) :-
746 json_pair(H, Name, Value),
747 json_write_string(Stream, Name),
748 write(Stream, ':'),
749 json_write_term(Value, Stream, State, Options),
750 ( T == []
751 -> true
752 ; ( json_write_state_width(State, 0)
753 -> write(Stream, ',')
754 ; write(Stream, ', ')
755 ),
756 write_pairs_hor(T, Stream, State, Options)
757 ).
758
759write_pairs_ver([], _, _, _).
760write_pairs_ver([H|T], Stream, State, Options) :-
761 indent(Stream, State),
762 json_pair(H, Name, Value),
763 json_write_string(Stream, Name),
764 write(Stream, ':'),
765 json_write_term(Value, Stream, State, Options),
766 ( T == []
767 -> true
768 ; write(Stream, ','),
769 write_pairs_ver(T, Stream, State, Options)
770 ).
771
772
773json_pair(Var, _, _) :-
774 var(Var),
775 !,
776 instantiation_error(Var).
777json_pair(Name=Value, Name, Value) :- !.
778json_pair(Name-Value, Name, Value) :- !.
779json_pair(NameValue, Name, Value) :-
780 compound(NameValue),
781 NameValue =.. [Name, Value],
782 !.
783json_pair(Pair, _, _) :-
784 type_error(json_pair, Pair).
785
786
787write_array_hor([], _, _, _).
788write_array_hor([H|T], Stream, State, Options) :-
789 json_write_term(H, Stream, State, Options),
790 ( T == []
791 -> write(Stream, ' ')
792 ; write(Stream, ', '),
793 write_array_hor(T, Stream, State, Options)
794 ).
795
796write_array_ver([], _, _, _).
797write_array_ver([H|T], Stream, State, Options) :-
798 indent(Stream, State),
799 json_write_term(H, Stream, State, Options),
800 ( T == []
801 -> true
802 ; write(Stream, ','),
803 write_array_ver(T, Stream, State, Options)
804 ).
805
806
807indent(Stream, State) :-
808 json_write_state_indent(State, Indent),
809 json_write_state_tab(State, Tab),
810 json_write_indent(Stream, Indent, Tab).
811
812step_indent(State0, State) :-
813 json_write_state_indent(State0, Indent),
814 json_write_state_step(State0, Step),
815 NewIndent is Indent+Step,
816 set_indent_of_json_write_state(NewIndent, State0, State).
817
818space_if_not_at_left_margin(Stream, State) :-
819 stream_pair(Stream, _, Write),
820 line_position(Write, LinePos),
821 ( LinePos == 0
822 ; json_write_state_indent(State, LinePos)
823 ),
824 !.
825space_if_not_at_left_margin(Stream, _) :-
826 put_char(Stream, ' ').
827
828
835
836json_print_length(Var, _, _, _, _) :-
837 var(Var),
838 !,
839 instantiation_error(Var).
840json_print_length(json(Pairs), Options, Max, Len0, Len) :-
841 !,
842 Len1 is Len0 + 2,
843 Len1 =< Max,
844 must_be(list, Pairs),
845 pairs_print_length(Pairs, Options, Max, Len1, Len).
846json_print_length(Dict, Options, Max, Len0, Len) :-
847 is_dict(Dict),
848 !,
849 dict_pairs(Dict, _Tag, Pairs),
850 Len1 is Len0 + 2,
851 Len1 =< Max,
852 pairs_print_length(Pairs, Options, Max, Len1, Len).
853json_print_length(Array, Options, Max, Len0, Len) :-
854 is_list(Array),
855 !,
856 Len1 is Len0 + 2,
857 Len1 =< Max,
858 array_print_length(Array, Options, Max, Len1, Len).
859json_print_length(Null, Options, Max, Len0, Len) :-
860 json_options_null(Options, Null),
861 !,
862 Len is Len0 + 4,
863 Len =< Max.
864json_print_length(False, Options, Max, Len0, Len) :-
865 json_options_false(Options, False),
866 !,
867 Len is Len0 + 5,
868 Len =< Max.
869json_print_length(True, Options, Max, Len0, Len) :-
870 json_options_true(Options, True),
871 !,
872 Len is Len0 + 4,
873 Len =< Max.
874json_print_length(Number, _Options, Max, Len0, Len) :-
875 number(Number),
876 !,
877 write_length(Number, AL, []),
878 Len is Len0 + AL,
879 Len =< Max.
880json_print_length(@(Id), _Options, Max, Len0, Len) :-
881 atom(Id),
882 !,
883 atom_length(Id, IdLen),
884 Len is Len0+IdLen,
885 Len =< Max.
886json_print_length(String, _Options, Max, Len0, Len) :-
887 string_len(String, Len0, Len),
888 !,
889 Len =< Max.
890json_print_length(AnyTerm, _Options, Max, Len0, Len) :-
891 write_length(AnyTerm, AL, []), 892 Len is Len0 + AL+2,
893 Len =< Max.
894
895pairs_print_length([], _, _, Len, Len).
896pairs_print_length([H|T], Options, Max, Len0, Len) :-
897 pair_len(H, Options, Max, Len0, Len1),
898 ( T == []
899 -> Len = Len1
900 ; Len2 is Len1 + 2,
901 Len2 =< Max,
902 pairs_print_length(T, Options, Max, Len2, Len)
903 ).
904
905pair_len(Pair, Options, Max, Len0, Len) :-
906 compound(Pair),
907 pair_nv(Pair, Name, Value),
908 !,
909 string_len(Name, Len0, Len1),
910 Len2 is Len1+2,
911 Len2 =< Max,
912 json_print_length(Value, Options, Max, Len2, Len).
913pair_len(Pair, _Options, _Max, _Len0, _Len) :-
914 type_error(pair, Pair).
915
916pair_nv(Name=Value, Name, Value) :- !.
917pair_nv(Name-Value, Name, Value) :- !.
918pair_nv(Term, Name, Value) :-
919 compound_name_arguments(Term, Name, [Value]).
920
921array_print_length([], _, _, Len, Len).
922array_print_length([H|T], Options, Max, Len0, Len) :-
923 json_print_length(H, Options, Max, Len0, Len1),
924 ( T == []
925 -> Len = Len1
926 ; Len2 is Len1+2,
927 Len2 =< Max,
928 array_print_length(T, Options, Max, Len2, Len)
929 ).
930
931string_len(String, Len0, Len) :-
932 atom(String),
933 !,
934 atom_length(String, AL),
935 Len is Len0 + AL + 2.
936string_len(String, Len0, Len) :-
937 string(String),
938 !,
939 string_length(String, AL),
940 Len is Len0 + AL + 2.
941
942
943 946
953
954is_json_term(Term) :-
955 default_json_options(Options),
956 is_json_term2(Options, Term).
957
958is_json_term(Term, Options) :-
959 make_json_options(Options, OptionTerm, _RestOptions),
960 is_json_term2(OptionTerm, Term).
961
962is_json_term2(_, Var) :-
963 var(Var), !, fail.
964is_json_term2(Options, json(Pairs)) :-
965 !,
966 is_list(Pairs),
967 maplist(is_json_pair(Options), Pairs).
968is_json_term2(Options, List) :-
969 is_list(List),
970 !,
971 maplist(is_json_term2(Options), List).
972is_json_term2(_, Primitive) :-
973 atomic(Primitive),
974 !. 975is_json_term2(Options, True) :-
976 json_options_true(Options, True).
977is_json_term2(Options, False) :-
978 json_options_false(Options, False).
979is_json_term2(Options, Null) :-
980 json_options_null(Options, Null).
981
982is_json_pair(_, Var) :-
983 var(Var), !, fail.
984is_json_pair(Options, Name=Value) :-
985 atom(Name),
986 is_json_term2(Options, Value).
987
988 991
1030
1031json_read_dict(Stream, Dict) :-
1032 json_read_dict(Stream, Dict, []).
1033
1034json_read_dict(Stream, Dict, Options) :-
1035 make_json_dict_options(Options, OptionTerm, _RestOptions),
1036 ( json_value_top(Stream, Term, OptionTerm)
1037 -> true
1038 ; syntax_error(illegal_json, Stream)
1039 ),
1040 term_to_dict(Term, Dict, OptionTerm).
1041
1042term_to_dict(Var, Var, _Options) :-
1043 var(Var),
1044 !.
1045term_to_dict(json(Pairs), Dict, Options) :-
1046 !,
1047 ( json_options_tag(Options, TagName),
1048 Tag \== '',
1049 select(TagName = Tag0, Pairs, NVPairs),
1050 to_atom(Tag0, Tag)
1051 -> json_dict_pairs(NVPairs, DictPairs, Options)
1052 ; json_options_default_tag(Options, DefTag),
1053 ( var(DefTag)
1054 -> true
1055 ; Tag = DefTag
1056 ),
1057 json_dict_pairs(Pairs, DictPairs, Options)
1058 ),
1059 dict_create(Dict, Tag, DictPairs).
1060term_to_dict(Value0, Value, _Options) :-
1061 atomic(Value0), Value0 \== [],
1062 !,
1063 Value = Value0.
1064term_to_dict(List0, List, Options) :-
1065 is_list(List0),
1066 !,
1067 terms_to_dicts(List0, List, Options).
1068term_to_dict(Special, Special, Options) :-
1069 ( json_options_true(Options, Special)
1070 ; json_options_false(Options, Special)
1071 ; json_options_null(Options, Special)
1072 ; json_options_end_of_file(Options, Special)
1073 ),
1074 !.
1075
1076json_dict_pairs([], [], _).
1077json_dict_pairs([Name=Value0|T0], [Name=Value|T], Options) :-
1078 term_to_dict(Value0, Value, Options),
1079 json_dict_pairs(T0, T, Options).
1080
1081terms_to_dicts([], [], _).
1082terms_to_dicts([Value0|T0], [Value|T], Options) :-
1083 term_to_dict(Value0, Value, Options),
1084 terms_to_dicts(T0, T, Options).
1085
1086to_atom(Tag, Atom) :-
1087 string(Tag),
1088 !,
1089 atom_string(Atom, Tag).
1090to_atom(Atom, Atom) :-
1091 atom(Atom).
1092
1099
1100json_write_dict(Stream, Dict) :-
1101 json_write_dict(Stream, Dict, []).
1102
1103json_write_dict(Stream, Dict, Options) :-
1104 make_json_write_state(Options, State, Options1),
1105 make_json_dict_options(Options1, OptionTerm, _RestOptions),
1106 json_write_term(Dict, Stream, State, OptionTerm).
1107
1108
1109make_json_dict_options(Options, Record, RestOptions) :-
1110 default_json_dict_options(Record0),
1111 set_json_options_fields(Options, Record0, Record, RestOptions).
1112
1123
1124atom_json_dict(Atom, Term, Options) :-
1125 ground(Atom),
1126 !,
1127 setup_call_cleanup(
1128 open_string(Atom, In),
1129 json_read_dict(In, Term, Options),
1130 close(In)).
1131atom_json_dict(Result, Term, Options) :-
1132 select_option(as(Type), Options, Options1, atom),
1133 ( type_term(Type, Result, Out)
1134 -> true
1135 ; must_be(oneof([atom,string,codes]), Type)
1136 ),
1137 with_output_to(Out,
1138 json_write_dict(current_output, Term, Options1)).
1139
1140 1143
1167
1168:- quasi_quotation_syntax(json). 1169
1170json(Content, Vars, Dict, Result) :-
1171 must_be(list, Dict),
1172 include(qq_var(Vars), Dict, QQDict),
1173 with_quasi_quotation_input(Content, Stream,
1174 json_read_dict(Stream, Result,
1175 [ qqdict(QQDict)
1176 ])).
1177
1178qq_var(Vars, _=Var) :-
1179 member(V, Vars),
1180 V == Var,
1181 !.
1182
1183
1184 1187
1188:- multifile
1189 prolog:error_message/3. 1190
1191prolog:error_message(syntax_error(json(Id))) -->
1192 [ 'JSON syntax error: ' ],
1193 json_syntax_error(Id).
1194
1195json_syntax_error(illegal_comment) -->
1196 [ 'Illegal comment' ].
1197json_syntax_error(illegal_string_escape) -->
1198 [ 'Illegal escape sequence in string' ].
1199json_syntax_error(illegal_surrogate_pair) -->
1200 [ 'Illegal escaped surrogate pair in string' ].
1201json_syntax_error(non_existing_var(Var, QQDict)) -->
1202 { maplist(arg(1), QQDict, Vars),
1203 Term =.. [json|Vars]
1204 },
1205 [ 'Variable ', ansi(code, '~w', [Var]),
1206 ' is not defined in {|',ansi(code,'~w',Term),'|||}'
1207 ].
1208
1209 1212
1213:- multifile sandbox:safe_primitive/1. 1214
1215sandbox:safe_primitive(json:json(_,_,_,_))