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 ]). 53:- use_module(library(record)). 54:- use_module(library(error)). 55:- use_module(library(option)). 56:- use_module(library(lists)). 57
58:- use_foreign_library(foreign(json)). 59
60:- multifile
61 json_write_hook/4, 62 json_dict_pairs/2. 63
64:- predicate_options(json_read/3, 3,
65 [ null(ground),
66 true(ground),
67 false(ground),
68 value_string_as(oneof([atom,string]))
69 ]). 70:- predicate_options(json_write/3, 3,
71 [ indent(nonneg),
72 step(positive_integer),
73 tab(positive_integer),
74 width(nonneg),
75 null(ground),
76 true(ground),
77 false(ground),
78 serialize_unknown(boolean)
79 ]). 80:- predicate_options(json_read_dict/3, 3,
81 [ tag(atom),
82 default_tag(atom),
83 pass_to(json_read/3, 3)
84 ]). 85:- predicate_options(json_write_dict/3, 3,
86 [ tag(atom),
87 pass_to(json_write/3, 3)
88 ]). 89:- predicate_options(is_json_term/2, 2,
90 [ null(ground),
91 true(ground),
92 false(ground)
93 ]). 94:- predicate_options(atom_json_term/3, 3,
95 [ as(oneof([atom,string,codes])),
96 pass_to(json_read/3, 3),
97 pass_to(json_write/3, 3)
98 ]). 99
121
122:- record json_options(
123 null:ground = @(null),
124 true:ground = @(true),
125 false:ground = @(false),
126 end_of_file:ground = error,
127 value_string_as:oneof([atom,string]) = atom,
128 tag:atom = '',
129 default_tag:atom). 130
131default_json_dict_options(
132 json_options(null, true, false, error, string, '', _)).
133
134
135 138
147
148atom_json_term(Atom, Term, Options) :-
149 ground(Atom),
150 !,
151 setup_call_cleanup(
152 open_string(Atom, In),
153 json_read(In, Term, Options),
154 close(In)).
155atom_json_term(Result, Term, Options) :-
156 select_option(as(Type), Options, Options1, atom),
157 ( type_term(Type, Result, Out)
158 -> true
159 ; must_be(oneof([atom,string,codes,chars]), Type)
160 ),
161 with_output_to(Out,
162 json_write(current_output, Term, Options1)).
163
164type_term(atom, Result, atom(Result)).
165type_term(string, Result, string(Result)).
166type_term(codes, Result, codes(Result)).
167type_term(chars, Result, chars(Result)).
168
169
170 173
246
247json_read(Stream, Term) :-
248 default_json_options(Options),
249 ( json_value_top(Stream, Term, Options)
250 -> true
251 ; syntax_error(illegal_json, Stream)
252 ).
253json_read(Stream, Term, Options) :-
254 make_json_options(Options, OptionTerm, _RestOptions),
255 ( json_value_top(Stream, Term, OptionTerm)
256 -> true
257 ; syntax_error(illegal_json, Stream)
258 ).
259
260json_value_top(Stream, Term, Options) :-
261 stream_property(Stream, type(binary)),
262 !,
263 setup_call_cleanup(
264 set_stream(Stream, encoding(utf8)),
265 json_value_top_(Stream, Term, Options),
266 set_stream(Stream, type(binary))).
267json_value_top(Stream, Term, Options) :-
268 json_value_top_(Stream, Term, Options).
269
270json_value_top_(Stream, Term, Options) :-
271 get_code(Stream, C0),
272 ws(C0, Stream, C1),
273 ( C1 == -1
274 -> json_options_end_of_file(Options, Action),
275 ( Action == error
276 -> syntax_error(unexpected_end_of_file, Stream)
277 ; Term = Action
278 )
279 ; json_term_top(C1, Stream, Term, Options)
280 ).
281
282json_value(Stream, Term, Next, Options) :-
283 get_code(Stream, C0),
284 ws(C0, Stream, C1),
285 ( C1 == -1
286 -> syntax_error(unexpected_end_of_file, Stream)
287 ; json_term(C1, Stream, Term, Next, Options)
288 ).
289
290json_term(C0, Stream, JSON, Next, Options) :-
291 json_term_top(C0, Stream, JSON, Options),
292 get_code(Stream, Next).
293
294json_term_top(0'{, Stream, json(Pairs), Options) :-
295 !,
296 ws(Stream, C),
297 json_pairs(C, Stream, Pairs, Options).
298json_term_top(0'[, Stream, Array, Options) :-
299 !,
300 ws(Stream, C),
301 json_array(C, Stream, Array, Options).
302json_term_top(0'", Stream, String, Options) :-
303 !,
304 get_code(Stream, C1),
305 json_string_codes(C1, Stream, Codes),
306 json_options_value_string_as(Options, Type),
307 codes_to_type(Type, Codes, String).
308json_term_top(0'-, Stream, Number, _Options) :-
309 !,
310 json_read_number(Stream, 0'-, Number).
311json_term_top(D, Stream, Number, _Options) :-
312 between(0'0, 0'9, D),
313 !,
314 json_read_number(Stream, D, Number).
315json_term_top(C, Stream, Constant, Options) :-
316 json_read_constant(C, Stream, ID),
317 json_constant(ID, Constant, Options).
318
319json_pairs(0'}, _, [], _) :- !.
320json_pairs(C0, Stream, [Pair|Tail], Options) :-
321 json_pair(C0, Stream, Pair, C, Options),
322 ws(C, Stream, Next),
323 ( Next == 0',
324 -> ws(Stream, C2),
325 json_pairs(C2, Stream, Tail, Options)
326 ; Next == 0'}
327 -> Tail = []
328 ; syntax_error(illegal_object, Stream)
329 ).
330
331json_pair(C0, Stream, Name=Value, Next, Options) :-
332 json_string_as_atom(C0, Stream, Name),
333 ws(Stream, C),
334 C == 0':,
335 json_value(Stream, Value, Next, Options).
336
337
338json_array(0'], _, [], _) :- !.
339json_array(C0, Stream, [Value|Tail], Options) :-
340 json_term(C0, Stream, Value, C, Options),
341 ws(C, Stream, Next),
342 ( Next == 0',
343 -> ws(Stream, C1),
344 json_array(C1, Stream, Tail, Options)
345 ; Next == 0']
346 -> Tail = []
347 ; syntax_error(illegal_array, Stream)
348 ).
349
350codes_to_type(atom, Codes, Atom) :-
351 atom_codes(Atom, Codes).
352codes_to_type(string, Codes, Atom) :-
353 string_codes(Atom, Codes).
354codes_to_type(codes, Codes, Codes).
355
356json_string_as_atom(0'", Stream, Atom) :-
357 get_code(Stream, C1),
358 json_string_codes(C1, Stream, Codes),
359 atom_codes(Atom, Codes).
360
361json_string_codes(0'", _, []) :- !.
362json_string_codes(0'\\, Stream, [H|T]) :-
363 !,
364 get_code(Stream, C0),
365 ( escape(C0, Stream, H)
366 -> true
367 ; syntax_error(illegal_string_escape, Stream)
368 ),
369 get_code(Stream, C1),
370 json_string_codes(C1, Stream, T).
371json_string_codes(-1, Stream, _) :-
372 !,
373 syntax_error(eof_in_string, Stream).
374json_string_codes(C, Stream, [C|T]) :-
375 get_code(Stream, C1),
376 json_string_codes(C1, Stream, T).
377
378escape(0'", _, 0'") :- !.
379escape(0'\\, _, 0'\\) :- !.
380escape(0'/, _, 0'/) :- !.
381escape(0'b, _, 0'\b) :- !.
382escape(0'f, _, 0'\f) :- !.
383escape(0'n, _, 0'\n) :- !.
384escape(0'r, _, 0'\r) :- !.
385escape(0't, _, 0'\t) :- !.
386escape(0'u, Stream, C) :-
387 get_XXXX(Stream, H),
388 ( hi_surrogate(H)
389 -> get_surrogate_tail(Stream, H, C)
390 ; C = H
391 ).
392
393get_XXXX(Stream, C) :-
394 get_xdigit(Stream, D1),
395 get_xdigit(Stream, D2),
396 get_xdigit(Stream, D3),
397 get_xdigit(Stream, D4),
398 C is D1<<12+D2<<8+D3<<4+D4.
399
400get_xdigit(Stream, D) :-
401 get_code(Stream, C),
402 code_type(C, xdigit(D)),
403 !.
404get_xdigit(Stream, _) :-
405 syntax_error(hexdigit_expected, Stream).
406
407get_surrogate_tail(Stream, Hi, Codepoint) :-
408 ( get_code(Stream, 0'\\),
409 get_code(Stream, 0'u),
410 get_XXXX(Stream, Lo),
411 surrogate([Hi, Lo], Codepoint)
412 -> true
413 ; syntax_error(illegal_surrogate_pair, Stream)
414 ).
415
416
417hi_surrogate(C) :-
418 C >= 0xD800, C < 0xDC00.
419
420lo_surrogate(C) :-
421 C >= 0xDC00, C < 0xE000.
422
423surrogate([Hi, Lo], Codepoint) :-
424 hi_surrogate(Hi),
425 lo_surrogate(Lo),
426 Codepoint is (Hi - 0xD800) * 0x400 + (Lo - 0xDC00) + 0x10000.
427
428json_read_constant(0't, Stream, true) :-
429 !,
430 must_see(`rue`, Stream, true).
431json_read_constant(0'f, Stream, false) :-
432 !,
433 must_see(`alse`, Stream, false).
434json_read_constant(0'n, Stream, null) :-
435 !,
436 must_see(`ull`, Stream, null).
437
438must_see([], _Stream, _).
439must_see([H|T], Stream, Name) :-
440 get_code(Stream, C),
441 ( C == H
442 -> true
443 ; syntax_error(json_expected(Name), Stream)
444 ),
445 must_see(T, Stream, Name).
446
447json_constant(true, Constant, Options) :-
448 !,
449 json_options_true(Options, Constant).
450json_constant(false, Constant, Options) :-
451 !,
452 json_options_false(Options, Constant).
453json_constant(null, Constant, Options) :-
454 !,
455 json_options_null(Options, Constant).
456
462
463ws(Stream, Next) :-
464 get_code(Stream, C0),
465 json_skip_ws(Stream, C0, Next).
466
467ws(C0, Stream, Next) :-
468 json_skip_ws(Stream, C0, Next).
469
470syntax_error(Message, Stream) :-
471 stream_error_context(Stream, Context),
472 throw(error(syntax_error(json(Message)), Context)).
473
474stream_error_context(Stream, stream(Stream, Line, LinePos, CharNo)) :-
475 stream_pair(Stream, Read, _),
476 character_count(Read, CharNo),
477 line_position(Read, LinePos),
478 line_count(Read, Line).
479
480
481 484
489
491
497
499
566
583
588
589:- record json_write_state(indent:nonneg = 0,
590 step:positive_integer = 2,
591 tab:positive_integer = 8,
592 width:nonneg = 72,
593 serialize_unknown:boolean = false
594 ). 595
596json_write(Stream, Term) :-
597 json_write(Stream, Term, []).
598json_write(Stream, Term, Options) :-
599 make_json_write_state(Options, State, Options1),
600 make_json_options(Options1, OptionTerm, _RestOptions),
601 json_write_term(Term, Stream, State, OptionTerm).
602
603json_write_term(Var, _, _, _) :-
604 var(Var),
605 !,
606 instantiation_error(Var).
607json_write_term(json(Pairs), Stream, State, Options) :-
608 !,
609 json_write_object(Pairs, Stream, State, Options).
610json_write_term(Dict, Stream, State, Options) :-
611 is_dict(Dict, Tag),
612 !,
613 json_pairs(Dict, Pairs0),
614 ( nonvar(Tag),
615 json_options_tag(Options, Name),
616 Name \== ''
617 -> Pairs = [Name-Tag|Pairs0]
618 ; Pairs = Pairs0
619 ),
620 json_write_object(Pairs, Stream, State, Options).
621json_write_term(List, Stream, State, Options) :-
622 is_list(List),
623 !,
624 space_if_not_at_left_margin(Stream, State),
625 write(Stream, '['),
626 ( json_write_state_width(State, Width),
627 ( Width == 0
628 -> true
629 ; json_write_state_indent(State, Indent),
630 json_print_length(List, Options, Width, Indent, _)
631 )
632 -> set_width_of_json_write_state(0, State, State2),
633 write_array_hor(List, Stream, State2, Options),
634 write(Stream, ']')
635 ; step_indent(State, State2),
636 write_array_ver(List, Stream, State2, Options),
637 indent(Stream, State),
638 write(Stream, ']')
639 ).
640
641json_write_term(Term, Stream, State, Options) :-
642 json_write_hook(Term, Stream, State, Options),
643 !.
644json_write_term(Number, Stream, _State, _Options) :-
645 number(Number),
646 !,
647 ( float(Number)
648 -> write(Stream, Number)
649 ; integer(Number)
650 -> write(Stream, Number)
651 ; Float is float(Number) 652 -> write(Stream, Float)
653 ).
654json_write_term(True, Stream, _State, Options) :-
655 json_options_true(Options, True),
656 !,
657 write(Stream, true).
658json_write_term(False, Stream, _State, Options) :-
659 json_options_false(Options, False),
660 !,
661 write(Stream, false).
662json_write_term(Null, Stream, _State, Options) :-
663 json_options_null(Options, Null),
664 !,
665 write(Stream, null).
666json_write_term(#(Text), Stream, _State, _Options) :-
667 !,
668 ( ( atom(Text)
669 ; string(Text)
670 )
671 -> json_write_string(Stream, Text)
672 ; term_string(Text, String),
673 json_write_string(Stream, String)
674 ).
675json_write_term(String, Stream, _State, _Options) :-
676 atom(String),
677 !,
678 json_write_string(Stream, String).
679json_write_term(String, Stream, _State, _Options) :-
680 string(String),
681 !,
682 json_write_string(Stream, String).
683json_write_term(AnyTerm, Stream, State, _Options) :-
684 ( json_write_state_serialize_unknown(State, true)
685 -> term_string(AnyTerm, String),
686 json_write_string(Stream, String)
687 ; type_error(json_term, AnyTerm)
688 ).
689
690json_pairs(Dict, Pairs) :-
691 json_dict_pairs(Dict, Pairs),
692 !.
693json_pairs(Dict, Pairs) :-
694 dict_pairs(Dict, _, Pairs).
695
696json_write_object(Pairs, Stream, State, Options) :-
697 space_if_not_at_left_margin(Stream, State),
698 write(Stream, '{'),
699 ( json_write_state_width(State, Width),
700 ( Width == 0
701 -> true
702 ; json_write_state_indent(State, Indent),
703 json_print_length(json(Pairs), Options, Width, Indent, _)
704 )
705 -> set_width_of_json_write_state(0, State, State2),
706 write_pairs_hor(Pairs, Stream, State2, Options),
707 write(Stream, '}')
708 ; step_indent(State, State2),
709 write_pairs_ver(Pairs, Stream, State2, Options),
710 indent(Stream, State),
711 write(Stream, '}')
712 ).
713
714
715write_pairs_hor([], _, _, _).
716write_pairs_hor([H|T], Stream, State, Options) :-
717 json_pair(H, Name, Value),
718 json_write_string(Stream, Name),
719 write(Stream, ':'),
720 json_write_term(Value, Stream, State, Options),
721 ( T == []
722 -> true
723 ; ( json_write_state_width(State, 0)
724 -> write(Stream, ',')
725 ; write(Stream, ', ')
726 ),
727 write_pairs_hor(T, Stream, State, Options)
728 ).
729
730write_pairs_ver([], _, _, _).
731write_pairs_ver([H|T], Stream, State, Options) :-
732 indent(Stream, State),
733 json_pair(H, Name, Value),
734 json_write_string(Stream, Name),
735 write(Stream, ':'),
736 json_write_term(Value, Stream, State, Options),
737 ( T == []
738 -> true
739 ; write(Stream, ','),
740 write_pairs_ver(T, Stream, State, Options)
741 ).
742
743
744json_pair(Var, _, _) :-
745 var(Var),
746 !,
747 instantiation_error(Var).
748json_pair(Name=Value, Name, Value) :- !.
749json_pair(Name-Value, Name, Value) :- !.
750json_pair(NameValue, Name, Value) :-
751 compound(NameValue),
752 NameValue =.. [Name, Value],
753 !.
754json_pair(Pair, _, _) :-
755 type_error(json_pair, Pair).
756
757
758write_array_hor([], _, _, _).
759write_array_hor([H|T], Stream, State, Options) :-
760 json_write_term(H, Stream, State, Options),
761 ( T == []
762 -> write(Stream, ' ')
763 ; write(Stream, ', '),
764 write_array_hor(T, Stream, State, Options)
765 ).
766
767write_array_ver([], _, _, _).
768write_array_ver([H|T], Stream, State, Options) :-
769 indent(Stream, State),
770 json_write_term(H, Stream, State, Options),
771 ( T == []
772 -> true
773 ; write(Stream, ','),
774 write_array_ver(T, Stream, State, Options)
775 ).
776
777
778indent(Stream, State) :-
779 json_write_state_indent(State, Indent),
780 json_write_state_tab(State, Tab),
781 json_write_indent(Stream, Indent, Tab).
782
783step_indent(State0, State) :-
784 json_write_state_indent(State0, Indent),
785 json_write_state_step(State0, Step),
786 NewIndent is Indent+Step,
787 set_indent_of_json_write_state(NewIndent, State0, State).
788
789space_if_not_at_left_margin(Stream, State) :-
790 stream_pair(Stream, _, Write),
791 line_position(Write, LinePos),
792 ( LinePos == 0
793 ; json_write_state_indent(State, LinePos)
794 ),
795 !.
796space_if_not_at_left_margin(Stream, _) :-
797 put_char(Stream, ' ').
798
799
806
807json_print_length(Var, _, _, _, _) :-
808 var(Var),
809 !,
810 instantiation_error(Var).
811json_print_length(json(Pairs), Options, Max, Len0, Len) :-
812 !,
813 Len1 is Len0 + 2,
814 Len1 =< Max,
815 must_be(list, Pairs),
816 pairs_print_length(Pairs, Options, Max, Len1, Len).
817json_print_length(Dict, Options, Max, Len0, Len) :-
818 is_dict(Dict),
819 !,
820 dict_pairs(Dict, _Tag, Pairs),
821 Len1 is Len0 + 2,
822 Len1 =< Max,
823 pairs_print_length(Pairs, Options, Max, Len1, Len).
824json_print_length(Array, Options, Max, Len0, Len) :-
825 is_list(Array),
826 !,
827 Len1 is Len0 + 2,
828 Len1 =< Max,
829 array_print_length(Array, Options, Max, Len1, Len).
830json_print_length(Null, Options, Max, Len0, Len) :-
831 json_options_null(Options, Null),
832 !,
833 Len is Len0 + 4,
834 Len =< Max.
835json_print_length(False, Options, Max, Len0, Len) :-
836 json_options_false(Options, False),
837 !,
838 Len is Len0 + 5,
839 Len =< Max.
840json_print_length(True, Options, Max, Len0, Len) :-
841 json_options_true(Options, True),
842 !,
843 Len is Len0 + 4,
844 Len =< Max.
845json_print_length(Number, _Options, Max, Len0, Len) :-
846 number(Number),
847 !,
848 write_length(Number, AL, []),
849 Len is Len0 + AL,
850 Len =< Max.
851json_print_length(@(Id), _Options, Max, Len0, Len) :-
852 atom(Id),
853 !,
854 atom_length(Id, IdLen),
855 Len is Len0+IdLen,
856 Len =< Max.
857json_print_length(String, _Options, Max, Len0, Len) :-
858 string_len(String, Len0, Len),
859 !,
860 Len =< Max.
861json_print_length(AnyTerm, _Options, Max, Len0, Len) :-
862 write_length(AnyTerm, AL, []), 863 Len is Len0 + AL+2,
864 Len =< Max.
865
866pairs_print_length([], _, _, Len, Len).
867pairs_print_length([H|T], Options, Max, Len0, Len) :-
868 pair_len(H, Options, Max, Len0, Len1),
869 ( T == []
870 -> Len = Len1
871 ; Len2 is Len1 + 2,
872 Len2 =< Max,
873 pairs_print_length(T, Options, Max, Len2, Len)
874 ).
875
876pair_len(Pair, Options, Max, Len0, Len) :-
877 compound(Pair),
878 pair_nv(Pair, Name, Value),
879 !,
880 string_len(Name, Len0, Len1),
881 Len2 is Len1+2,
882 Len2 =< Max,
883 json_print_length(Value, Options, Max, Len2, Len).
884pair_len(Pair, _Options, _Max, _Len0, _Len) :-
885 type_error(pair, Pair).
886
887pair_nv(Name=Value, Name, Value) :- !.
888pair_nv(Name-Value, Name, Value) :- !.
889pair_nv(Term, Name, Value) :-
890 compound_name_arguments(Term, Name, [Value]).
891
892array_print_length([], _, _, Len, Len).
893array_print_length([H|T], Options, Max, Len0, Len) :-
894 json_print_length(H, Options, Max, Len0, Len1),
895 ( T == []
896 -> Len = Len1
897 ; Len2 is Len1+2,
898 Len2 =< Max,
899 array_print_length(T, Options, Max, Len2, Len)
900 ).
901
902string_len(String, Len0, Len) :-
903 atom(String),
904 !,
905 atom_length(String, AL),
906 Len is Len0 + AL + 2.
907string_len(String, Len0, Len) :-
908 string(String),
909 !,
910 string_length(String, AL),
911 Len is Len0 + AL + 2.
912
913
914 917
924
925is_json_term(Term) :-
926 default_json_options(Options),
927 is_json_term2(Options, Term).
928
929is_json_term(Term, Options) :-
930 make_json_options(Options, OptionTerm, _RestOptions),
931 is_json_term2(OptionTerm, Term).
932
933is_json_term2(_, Var) :-
934 var(Var), !, fail.
935is_json_term2(Options, json(Pairs)) :-
936 !,
937 is_list(Pairs),
938 maplist(is_json_pair(Options), Pairs).
939is_json_term2(Options, List) :-
940 is_list(List),
941 !,
942 maplist(is_json_term2(Options), List).
943is_json_term2(_, Primitive) :-
944 atomic(Primitive),
945 !. 946is_json_term2(Options, True) :-
947 json_options_true(Options, True).
948is_json_term2(Options, False) :-
949 json_options_false(Options, False).
950is_json_term2(Options, Null) :-
951 json_options_null(Options, Null).
952
953is_json_pair(_, Var) :-
954 var(Var), !, fail.
955is_json_pair(Options, Name=Value) :-
956 atom(Name),
957 is_json_term2(Options, Value).
958
959 962
1001
1002json_read_dict(Stream, Dict) :-
1003 json_read_dict(Stream, Dict, []).
1004
1005json_read_dict(Stream, Dict, Options) :-
1006 make_json_dict_options(Options, OptionTerm, _RestOptions),
1007 ( json_value_top(Stream, Term, OptionTerm)
1008 -> true
1009 ; syntax_error(illegal_json, Stream)
1010 ),
1011 term_to_dict(Term, Dict, OptionTerm).
1012
1013term_to_dict(json(Pairs), Dict, Options) :-
1014 !,
1015 ( json_options_tag(Options, TagName),
1016 Tag \== '',
1017 select(TagName = Tag0, Pairs, NVPairs),
1018 to_atom(Tag0, Tag)
1019 -> json_dict_pairs(NVPairs, DictPairs, Options)
1020 ; json_options_default_tag(Options, DefTag),
1021 ( var(DefTag)
1022 -> true
1023 ; Tag = DefTag
1024 ),
1025 json_dict_pairs(Pairs, DictPairs, Options)
1026 ),
1027 dict_create(Dict, Tag, DictPairs).
1028term_to_dict(Value0, Value, _Options) :-
1029 atomic(Value0), Value0 \== [],
1030 !,
1031 Value = Value0.
1032term_to_dict(List0, List, Options) :-
1033 is_list(List0),
1034 !,
1035 terms_to_dicts(List0, List, Options).
1036term_to_dict(Special, Special, Options) :-
1037 ( json_options_true(Options, Special)
1038 ; json_options_false(Options, Special)
1039 ; json_options_null(Options, Special)
1040 ; json_options_end_of_file(Options, Special)
1041 ),
1042 !.
1043
1044json_dict_pairs([], [], _).
1045json_dict_pairs([Name=Value0|T0], [Name=Value|T], Options) :-
1046 term_to_dict(Value0, Value, Options),
1047 json_dict_pairs(T0, T, Options).
1048
1049terms_to_dicts([], [], _).
1050terms_to_dicts([Value0|T0], [Value|T], Options) :-
1051 term_to_dict(Value0, Value, Options),
1052 terms_to_dicts(T0, T, Options).
1053
1054to_atom(Tag, Atom) :-
1055 string(Tag),
1056 !,
1057 atom_string(Atom, Tag).
1058to_atom(Atom, Atom) :-
1059 atom(Atom).
1060
1067
1068json_write_dict(Stream, Dict) :-
1069 json_write_dict(Stream, Dict, []).
1070
1071json_write_dict(Stream, Dict, Options) :-
1072 make_json_write_state(Options, State, Options1),
1073 make_json_dict_options(Options1, OptionTerm, _RestOptions),
1074 json_write_term(Dict, Stream, State, OptionTerm).
1075
1076
1077make_json_dict_options(Options, Record, RestOptions) :-
1078 default_json_dict_options(Record0),
1079 set_json_options_fields(Options, Record0, Record, RestOptions).
1080
1091
1092atom_json_dict(Atom, Term, Options) :-
1093 ground(Atom),
1094 !,
1095 setup_call_cleanup(
1096 open_string(Atom, In),
1097 json_read_dict(In, Term, Options),
1098 close(In)).
1099atom_json_dict(Result, Term, Options) :-
1100 select_option(as(Type), Options, Options1, atom),
1101 ( type_term(Type, Result, Out)
1102 -> true
1103 ; must_be(oneof([atom,string,codes]), Type)
1104 ),
1105 with_output_to(Out,
1106 json_write_dict(current_output, Term, Options1)).
1107
1108
1109 1112
1113:- multifile
1114 prolog:error_message/3. 1115
1116prolog:error_message(syntax_error(json(Id))) -->
1117 [ 'JSON syntax error: ' ],
1118 json_syntax_error(Id).
1119
1120json_syntax_error(illegal_comment) -->
1121 [ 'Illegal comment' ].
1122json_syntax_error(illegal_string_escape) -->
1123 [ 'Illegal escape sequence in string' ].
1124json_syntax_error(illegal_surrogate_pair) -->
1125 [ 'Illegal escaped surrogate pair in string' ]