{ $values { "string" "a string in JSON format" } { "object" "a deserialized object" } }
{ $description "Deserializes the JSON formatted string into a Factor object. JSON objects are converted to Factor hashtables. All other JSON objects convert to their obvious Factor equivalents." } ;
-HELP: read-jsons
+HELP: read-json-objects
{ $values { "objects" "a vector of deserialized objects" } }
{ $description "Reads JSON formatted strings into a vector of Factor object until the end of the stream is reached. JSON objects are converted to Factor hashtables. All other JSON objects convert to their obvious Factor equivalents." } ;
ARTICLE: "json.reader" "JSON reader"
"The " { $vocab-link "json.reader" } " vocabulary defines a word for parsing strings in JSON format."
-{ $subsections json> read-jsons } ;
+{ $subsections json> read-json-objects } ;
ABOUT: "json.reader"
{ 0 } [ " 0 " json> ] unit-test
{ V{ H{ { "a" "b" } } H{ { "c" "d" } } } }
-[ "{\"a\": \"b\"} {\"c\": \"d\"}" [ read-jsons ] with-string-reader ] unit-test
+[ "{\"a\": \"b\"} {\"c\": \"d\"}" [ read-json-objects ] with-string-reader ] unit-test
! empty objects are allowed as values in objects
{ H{ { "foo" H{ } } } } [ "{ \"foo\" : {}}" json> ] unit-test
[ "<!doctype html>\n<html>\n<head>\n " json> ]
[ not-a-json-number? ] must-fail-with
+
+{ H{ } } [ "" json> ] unit-test
! Copyright (C) 2008 Peter Burns, 2009 Philipp Winkler
! See http://factorcode.org/license.txt for BSD license.
-
-USING: assocs combinators fry io io.streams.string json kernel
-kernel.private math math.order math.parser namespaces sbufs
-sequences sequences.private strings vectors ;
-
+USING: assocs combinators fry io io.encodings.utf8 io.files
+io.streams.string json kernel kernel.private math math.order
+math.parser namespaces sbufs sequences sequences.private strings
+vectors ;
IN: json.reader
<PRIVATE
[ pick json-number [ suffix! ] dip [ scan ] when* ]
} case ;
-: stream-json-read ( stream -- objects )
+: json-read-input ( stream -- objects )
V{ } clone over '[ _ stream-read1 dup ] [ scan ] while drop nip ;
+! If there are no json objects, return an empty hashtable
+! This happens for empty files.
+: first-json-object ( objects -- obj )
+ [ H{ } clone ] [ first ] if-empty ;
+
PRIVATE>
-: read-jsons ( -- objects )
- input-stream get stream-json-read ;
+: read-json-objects ( -- objects )
+ input-stream get json-read-input ;
GENERIC: json> ( string -- object )
M: string json>
- [ read-jsons first ] with-string-reader ;
+ [ read-json-objects first-json-object ] with-string-reader ;
+
+: path>json ( path -- json )
+ utf8 [ read-json-objects first-json-object ] with-file-reader ;