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