json.jl

Pollen/formats/json.jl is a source file in module Pollen

			
			
			
			
			
			"""
			

			    JSONFormat() <: Format

			

			Format for reading and writing trees from and to JSON.

			

			Trees nodes are encoded as JSON objects:

			

			```julia-repl

			julia> render(Node(:p, "Hello", nothing), JSONFormat()) |> println

			

			{"attributes":{},"tag":"p","children":["Hello", null]}

			```

			

			Encoding to JSON is lossless only when leaf and attribute values

			are valid JSON types. Richer leaf values will be converted to

			a dictionary of MIME type representations to allow serialization

			and rich display upon deserialization.

			"""
			

			
			
			Base
			.
			
			@
			kwdef
			 
			
			
			struct
			
			 

	
			JSONFormat
			 
			<:
			 

	
			Format
			
			
    
			
			mimes
			 
			=
			 

	
			MIMES
			
    
			
			firstmimeonly
			 
			=
			 
			true
			

			end
			

			

			
			

	
			formatextension
			(
			
			::

	
			JSONFormat
			)
			 
			=
			 
			
			"
			json
			"

Outputting JSON


			
			
			
			
			
			"""
			

			    tojson(::JSONFormat, tree)

			

			Convert a `tree` into a JSON-compatible representation, i.e.

			one that only uses JSON datatypes (`Dict`, `String`, `Number`, `Nothing`).

			"""
			

			
			function
			 

	
			tojson
			 
			end
			

			

			
			

	
			tojson
			(
			
			tree
			::

	
			XTree
			)
			 
			=
			 
			

	
			tojson
			(
			

	
			JSONFormat
			(
			)
			,
			 
			tree
			)
			

			
			function
			 
			

	
			tojson
			(
			
			format
			::

	
			JSONFormat
			,
			 
			
			node
			::

	
			Node
			)
			
			
    
			
			Dict
			(
			
			
			:
			type
			 
			=>
			 
			
			"
			node
			"
			,
			
         
			
			
			:

	
			tag
			 
			=>
			 
			

	
			tag
			(
			node
			)
			,
			
         
			
			
			:
			children
			 
			=>
			 
			
			[
			
			

	
			tojson
			(
			format
			,
			 
			ch
			)
			 
			for
			
			 
			ch
			 
			in
			 
			
			children
			(
			node
			)
			]
			,
			
         
			
			
			:

	
			attributes
			 
			=>
			 
			

	
			attributes
			(
			node
			)
			)
			

			end
			

			

			
			

	
			tojson
			(
			
			::

	
			JSONFormat
			,
			 
			
			::
			

	
			Leaf
			{
			Nothing
			}
			)
			 
			=
			 
			nothing
			

			
			

	
			tojson
			(
			
			::

	
			JSONFormat
			,
			 
			
			leaf
			::
			

	
			Leaf
			{
			String
			}
			)
			 
			=
			 
			
			leaf
			[
			]

non-primitive leaf values are stored as mimetype dicts


			
			
			
			function
			 
			

	
			tojson
			(
			
			format
			::

	
			JSONFormat
			,
			 
			
			leaf
			::

	
			Leaf
			)
			
			
    
			
			mimestrings
			 
			=
			 
			

	
			asmimestrings
			(
			
			leaf
			[
			]
			,
			 
			
			format
			.
			
			mimes
			
			;
			 
			
			firstonly
			 
			=
			 
			
			format
			.
			
			firstmimeonly
			)
			
    
			
			return
			 
			
			Dict
			(
			
			
			:
			type
			 
			=>
			 
			
			"
			leaf
			"
			,
			 
			
			
			:
			mimes
			 
			=>
			 
			mimestrings
			)
			

			end
			

			

			
			function
			 
			

	
			render!
			(
			
			io
			::
			IO
			,
			 
			
			tree
			::

	
			XTree
			,
			 
			
			::

	
			JSONFormat
			)
			
			
    
			
			
			JSON3
			.
			
			write
			(
			io
			,
			 
			

	
			tojson
			(
			tree
			)
			)
			

			end

Inputting JSON


			
			
			
			function
			 
			

	
			parse
			(
			
			io
			::
			IO
			,
			 
			
			format
			::

	
			JSONFormat
			)
			
			
    
			
			data
			 
			=
			 
			
			
			JSON3
			.
			
			read
			(
			io
			)
			
    
			
			return
			 
			

	
			fromjson
			(
			format
			,
			 
			data
			)
			

			end
			

			

			
			function
			 

	
			fromjson
			 
			end
			

			
			

	
			fromjson
			(
			data
			)
			 
			=
			 
			

	
			fromjson
			(
			

	
			JSONFormat
			(
			)
			,
			 
			data
			)
			

			

			
			function
			 
			

	
			fromjson
			(
			
			format
			::

	
			JSONFormat
			,
			 
			
			data
			::
			
			Union
			{
			
			<:
			Dict
			,
			 
			
			<:
			
			JSON3
			.
			
			Object
			}
			)
			
			
    
			
			type
			 
			=
			 
			
			data
			[
			
			:
			type
			]
			
    
			
			if
			
			 
			type
			 
			==
			 
			
			"
			leaf
			"
			
			
        
			
			return
			 
			

	
			Leaf
			(
			

	
			PreRendered
			(
			
			Dict
			(
			
			
			
			MIME
			(
			m
			)
			 
			=>
			 
			val
			 
			for
			
			 
			
			(
			m
			,
			 
			val
			)
			 
			in
			 
			
			data
			[
			
			:
			mimes
			]
			)
			)
			)
			
    
			
			elseif
			
			 
			type
			 
			==
			 
			
			"
			node
			"
			
			
        
			
			return
			 
			

	
			Node
			(
			
			Symbol
			(
			
			data
			[
			
			:

	
			tag
			]
			)
			,
			
                    
			

	
			XTree
			[
			
			

	
			fromjson
			(
			format
			,
			 
			ch
			)
			 
			for
			
			 
			ch
			 
			in
			 
			
			data
			[
			
			:
			children
			]
			]
			,
			
                    
			
			Dict
			(
			
			data
			[
			
			:

	
			attributes
			]
			)
			)
			
    
			else
			
			
        
			
			throw
			(
			
			ArgumentError
			(
			
			"
			Could not parse a tree from JSON data 
			$
			(
			data
			)
			"
			)
			)
			
    
			end
			

			end
			

			

			
			

	
			fromjson
			(
			
			::

	
			JSONFormat
			,
			 
			
			::
			Nothing
			)
			 
			=
			 
			

	
			Leaf
			(
			nothing
			)
			

			
			

	
			fromjson
			(
			
			::

	
			JSONFormat
			,
			 
			
			str
			::
			String
			)
			 
			=
			 
			

	
			Leaf
			(
			str
			)

PreRendered allows reading back in leaf values with rich types that were converted to mime representations.


			
			
			
			
			struct
			 

	
			PreRendered
			
			
    
			
			mimestrings
			::
			
			Dict
			{
			MIME
			,
			 
			String
			}
			

			end
			

			

			
			

	
			prerender
			(
			x
			)
			 
			=
			 
			

	
			PreRendered
			(
			

	
			asmimestrings
			(
			x
			,
			 

	
			MIMES
			
			;
			 
			
			firstonly
			 
			=
			 
			false
			)
			)
			

			

			
			function
			 
			

	
			asmimestrings
			(
			
			x
			::

	
			PreRendered
			,
			 
			
			mimes
			 
			=
			 

	
			MIMES
			
			;
			 
			
			firstonly
			 
			=
			 
			false
			)
			
			
    
			
			mimestrings
			 
			=
			 
			
			
			Dict
			{
			MIME
			,
			 
			String
			}
			(
			)
			
    
			
			for
			
			 
			mime
			 
			in
			 
			mimes
			
			
        
			
			if
			
			 
			mime
			 
			in
			 
			
			keys
			(
			
			x
			.
			
			mimestrings
			)
			
			
            
			
			
			mimestrings
			[
			mime
			]
			 
			=
			 
			
			
			x
			.
			
			mimestrings
			[
			mime
			]
			
            
			
			firstonly
			 
			&&
			 
			break
			
        
			end
			
    
			end
			
    
			
			return
			 
			mimestrings
			

			end
			

			

			
			function
			 
			
			
			Base
			.
			
			show
			(
			
			io
			::
			IO
			,
			 
			
			pre
			::

	
			PreRendered
			)
			
			
    
			
			print
			(
			io
			,
			
          
			
			"
			Prerendered(
			$
			(
			
			collect
			(
			
			keys
			(
			
			pre
			.
			
			mimestrings
			)
			)
			)
			)
			"
			)
			

			end
			

			

			
			@
			testset
			 
			
			"
			JSONFormat
			"
			 
			
			begin
			
    
			
			format
			 
			=
			 
			

	
			JSONFormat
			(
			
			firstmimeonly
			 
			=
			 
			false
			)
			

			
    
			
			@
			testset
			 
			
			"
			Leaves
			"
			 
			
			begin
			
        
			
			@
			test
			
			 
			

	
			render
			(
			

	
			Leaf
			(
			
			"
			Hello
			"
			)
			,
			 
			format
			)
			 
			==
			 
			
			"
			\"Hello\"
			"
			
        
			
			@
			test
			
			 
			

	
			render
			(
			

	
			Leaf
			(
			nothing
			)
			,
			 
			format
			)
			 
			==
			 
			
			"
			null
			"
			
    
			end
			

			
    
			
			@
			testset
			 
			
			"
			PreRendered
			"
			 
			
			begin
			
        
			
			leaf
			 
			=
			 
			

	
			Leaf
			(
			
			
			Base
			.
			
			HTML
			(
			
			"
			<p>Hello</p>
			"
			)
			)
			
        
			
			leaf_
			 
			=
			 
			

	
			parse
			(
			

	
			render
			(
			leaf
			,
			 
			format
			)
			,
			 
			format
			)
			
        
			
			@
			test
			
			 
			leaf_
			 
			isa
			 
			

	
			Leaf
			{

	
			PreRendered
			}
			
        
			
			@
			test
			
			 
			
			
			
			leaf_
			[
			]
			.
			
			mimestrings
			[
			
			MIME
			(
			
			"
			text/html
			"
			)
			]
			 
			==
			 
			
			"
			<p>Hello</p>
			"
			
    
			end
			

			
    
			
			@
			testset
			 
			
			"
			Round-trip
			"
			 
			
			begin
			
        
			
			tree
			 
			=
			 
			

	
			Node
			(
			
			:
			doc
			,
			 
			

	
			Node
			(
			
			:
			p
			,
			 
			
			"
			hi
			"
			,
			 
			nothing
			
			;
			 
			
			attr
			 
			=
			 
			
			"
			val
			"
			)
			)
			
        
			
			@
			test
			
			 
			
			
			Pollen
			.
			

	
			parse
			(
			
			
			Pollen
			.
			

	
			render
			(
			tree
			,
			 
			format
			)
			,
			 
			format
			)
			 
			==
			 
			tree
			
    
			end
			

			end