--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2012-2013 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Writing to and reading from the Json format.
+# Based on the json0 C library
+module json
+
+import jsonable
+import json_reader
+import json_writer
+
+redef class String
+ fun json_load_from_file : nullable Map[ String, nullable Jsonable ]
+ do
+ var f = new IFStream.open( self )
+ var data = f.read_all.json_to_object
+ f.close
+
+ return data.as(not null) # ( Map[ String, nullable Jsonable ] )
+ end
+end
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2012-2013 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# This file is free software, which comes along with NIT. This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. You can modify it is you want, provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You are allowed to redistribute it and sell it, alone or is a part of
+# another product.
+
+# Deserialisation from the Json format to Nit objects
+module json_reader
+
+intrude import jsonable
+
+redef class String
+ # Deserializes this String and return its value as a Map[String, nullable Jsonable]
+ # On error, null is returned.
+ fun json_to_object : nullable Map[String, nullable Jsonable] import String::from_cstring, JsonObject::json_to_map `{
+ char *native_recv;
+ json_object *jobj;
+ nullable_Map map;
+
+ native_recv = String_to_cstring( recv );
+ jobj = json_tokener_parse( native_recv );
+ map = JsonObject_json_to_map( jobj );
+
+ /*json_object_put( jobj );*/
+ return map;
+ `}
+end
+
+redef extern JsonObject
+ # Get this json object as a Map
+ private fun json_to_map : nullable Map[String, nullable Jsonable] import String::from_cstring, String::to_cstring, HashMap, HashMap::[]=, json_cross, HashMap[String,nullable Jsonable] as( nullable Map[String,nullable Jsonable] ), String as ( Object ), nullable Jsonable as (nullable Object) `{
+ HashMap map;
+ String nit_key;
+ nullable_Jsonable nit_val;
+
+ map = new_HashMap();
+
+ { /* prevents "mixed declaration and code" warning for C90 */
+ json_object_object_foreach( recv, key, val ) {
+ nit_key = new_String_from_cstring( key );
+ nit_val = JsonObject_json_cross( val , json_object_get_type( val ) );
+
+ HashMap__index_assign( map, String_as_Object( nit_key ), nullable_Jsonable_as_nullable_Object( nit_val ) );
+ }
+ }
+
+ return HashMap_as_nullable_Map( map );
+ `}
+
+ # Get this json object as a Bool
+ private fun json_to_bool : Bool `{
+ return json_object_get_boolean( recv );
+ `}
+
+ # Get this json object as a Float
+ private fun json_to_float : Float `{
+ return json_object_get_double( recv );
+ `}
+
+ # Get this json object as an Int
+ private fun json_to_int : Int `{
+ return json_object_get_int( recv );
+ `}
+
+ # Get this json object as a Sequence
+ private fun json_to_sequence : Sequence[Jsonable] import Array, Array::push, Array[nullable Jsonable] as ( Sequence[nullable Jsonable] ), json_cross `{
+ array_list* jlist;
+ json_object* jobj;
+ nullable_Jsonable obj;
+ Array dest;
+ int i;
+ int len;
+
+ jlist = json_object_get_array( recv );
+ len = json_object_array_length( recv );
+ dest = new_Array();
+ for ( i = 0; i < len; i ++ ) {
+ jobj = json_object_array_get_idx( recv, i );
+ obj = JsonObject_json_cross( jobj, json_object_get_type( jobj ) );
+ Array_push( dest, nullable_Jsonable_as_nullable_Object( obj ) );
+ }
+
+ return Array_as_Sequence( dest );
+ `}
+
+ # Get this json object as a String
+ private fun json_to_string : String import String::from_cstring `{
+ char *cstring;
+ cstring = json_object_get_string( recv );
+ return new_String_from_cstring( cstring );
+ `}
+
+ # Intermediate function to convert to gt this Json object as a given type.
+ # Imlemented in Nit because Nit should manage all possible typing-related work.
+ private fun json_cross( json_type : Int ) : nullable Jsonable
+ do
+ if json_type == 0 then # null
+ return null
+ else if json_type == 1 then # Bool
+ return json_to_bool
+ else if json_type == 2 then # Float
+ return json_to_float
+ else if json_type == 3 then # Int
+ return json_to_int
+ else if json_type == 4 then # Map
+ return json_to_map
+ else if json_type == 5 then # Sequence
+ return json_to_sequence
+ else if json_type == 6 then # String
+ return json_to_string
+ else
+ print "WARNING: Unrecongnized json object type id: {json_type}"
+ return null
+ end
+ end
+end
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2012-2013 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# This file is free software, which comes along with NIT. This software is
+# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. You can modify it is you want, provided this header
+# is kept unaltered, and a notification of the changes is added.
+# You are allowed to redistribute it and sell it, alone or is a part of
+# another product.
+
+# Serialisation from Nit objects to the Json format
+module json_writer
+
+intrude import jsonable
+
+redef interface Jsonable
+ # Get a JsonObject representing this instance, specific to the C library
+ private fun to_json_object : JsonObject is abstract
+end
+
+# Will ignore non-jsonable
+redef class Map[ K, V ]
+ # Get a json-formatted string of this map
+ fun to_json( pretty: Bool ) : String import to_json_object `{
+ json_object *jobj;
+ char *json_native_string;
+ String json_string;
+
+ jobj = Map_to_json_object( recv );
+ if ( pretty )
+ json_native_string = json_object_to_json_string_ext( jobj, JSON_C_TO_STRING_PRETTY );
+ else
+ json_native_string = json_object_to_json_string_ext( jobj, JSON_C_TO_STRING_PLAIN );
+ json_string = new_String_from_cstring( json_native_string );
+ return json_string;
+ `}
+
+ redef fun to_json_object
+ do
+ var jobj = new JsonObject
+
+ var iter = iterator
+ while iter.is_ok do
+ var key = iter.key
+ if key isa String then
+ var val = iter.item
+ if val isa Jsonable then
+ var jsubobj = val.to_json_object
+ jobj.add( key, jsubobj )
+ else if val == null then
+ jobj.add( key, null )
+ else
+ print "WARNING: value \"{val}\" not jsonable, cannot be converted to json."
+ end
+ else
+ print "WARNING: key \"{key}\" not a string, cannot be converted to json."
+ end
+
+ iter.next
+ end
+ return jobj
+ end
+end
+
+redef class Sequence[ E ]
+ redef fun to_json_object
+ do
+ var jarray = new JsonArray
+ for e in self do
+ if e isa nullable Jsonable then
+ if e == null then
+ jarray.push( null )
+ else
+ var obj = e.to_json_object
+ jarray.push( obj )
+ end
+ else
+ print "WARNING: element \"{e}\" not a Jsonable, cannot be converted to json."
+ end
+ end
+
+ return jarray
+ end
+end
+
+redef class String
+ redef fun to_json_object import String::from_cstring `{
+ char *native_recv = String_to_cstring( recv );
+ return json_object_new_string( native_recv );
+ `}
+end
+
+redef class Int
+ redef fun to_json_object `{
+ return json_object_new_int( recv );
+ `}
+end
+
+redef class Bool
+ redef fun to_json_object `{
+ return json_object_new_boolean( recv );
+ `}
+end
+
+redef class Float
+ redef fun to_json_object `{
+ return json_object_new_double( recv );
+ `}
+end
+
+redef class JsonObject
+ new `{ return json_object_new_object(); `}
+
+ # Add a key and value to the object
+ fun add( key : String, val : nullable JsonObject ) import String::to_cstring, nullable JsonObject as not nullable `{
+ char* native_key;
+
+ native_key = String_to_cstring( key );
+
+ if ( JsonObject_is_null(val) ) {
+ json_object_object_add( recv, native_key, NULL );
+ } else {
+ json_object *jobj;
+ jobj = JsonObject_as_not_null( val );
+ json_object_object_add( recv, native_key, jobj );
+ }
+ `}
+end
+
+private extern JsonArray
+ super JsonObject
+
+ new `{ return json_object_new_array(); `}
+
+ fun push( val : nullable JsonObject ) `{
+ if ( JsonObject_is_null(val) )
+ json_object_array_add( recv, NULL );
+ else
+ json_object_array_add( recv, JsonObject_as_not_null(val) );
+ `}
+end
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2012-2013 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Basic json related functionalities
+module jsonable
+
+in "C Header" `{
+ #define __STRICT_ANSI__
+ #include <json/json.h>
+`}
+
+# Type supported by the Json format
+interface Jsonable
+end
+
+# Main object type used by C library
+private extern JsonObject `{ json_object* `}
+ # Give up ownership of this object and decrease the reference count.
+ fun put `{ json_object_put( recv ); `}
+
+ # Aquire ownership of this object and increase the reference count.
+ fun get `{ json_object_get( recv ); `}
+end
+
+redef class Sequence[ V ]
+ super Jsonable
+end
+
+# Can b converted to a Json object
+redef class Map[ K, V ]
+ super Jsonable
+end
+
+redef class String
+ super Jsonable
+end
+
+redef class Int
+ super Jsonable
+end
+
+redef class Bool
+ super Jsonable
+end
+
+redef class Float
+ super Jsonable
+end
--- /dev/null
+--cc-lib-name json
test_ni_
test_ffi_
test_gtk
+test_json
calculator
nitc
nitdoc
test_ni_
test_ffi_
test_gtk
+test_json
calculator
nitc
nitdoc
test_ni_
test_ffi_
test_gtk
+test_json
calculator
nitc
nitdoc
test_math
test_mem
test_gtk
+test_json
calculator
shoot_logic
bench_
--- /dev/null
+../lib/json/json_reader.nit: In function 'JsonObject_json_to_string___impl':
+../lib/json/json_reader.nit:96:11: warning: assignment discards 'const' qualifier from pointer target type [enabled by default]
+../lib/json/json_writer.nit: In function 'Map_to_json___impl':
+../lib/json/json_writer.nit:34:23: warning: assignment discards 'const' qualifier from pointer target type [enabled by default]
+../lib/json/json_writer.nit:36:23: warning: assignment discards 'const' qualifier from pointer target type [enabled by default]
+{"int":"1234","float":"0.1234","str":"str","null": null}
+{"int":1234,"float":0.123400,"str":"str","null":null}
+{
+ "int":1234,
+ "float":0.123400,
+ "str":"str",
+ "null":null
+}
+{"arr":"123","obj":"{"int":"123","float":"-234.449997"}"}
+{"arr":[1,2,3],"obj":{"int":123,"float":-234.449997}}
+{
+ "arr":[
+ 1,
+ 2,
+ 3
+ ],
+ "obj":{
+ "int":123,
+ "float":-234.449997
+ }
+}
+{"arr":"12.3str","obj":"{"int":"123","float":"-234.449997"}"}
+{"arr":[1,2.300000,null,"str"],"obj":{"int":123,"float":-234.449997}}
+{
+ "arr":[
+ 1,
+ 2.300000,
+ null,
+ "str"
+ ],
+ "obj":{
+ "int":123,
+ "float":-234.449997
+ }
+}
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2012-2013 Alexis Laferrière <alexis.laf@xymus.net>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+module test_json
+
+import json
+
+redef class HashMap[K,V]
+ redef fun to_s
+ do
+ var es = new Array[String]
+ for k, v in self do
+ if v != null then
+ es.add( "\"{k}\":\"{v}\"" )
+ else
+ es.add( "\"{k}\": null" )
+ end
+ end
+ return "\{{es.join(",")}\}"
+ end
+end
+
+redef class String
+ fun parse_and_display
+ do
+ var json_map = json_to_object
+ if json_map != null then
+ print json_map
+ print json_map.to_json(false)
+ print json_map.to_json(true)
+ else
+ print "Conversion to json failed."
+ end
+ end
+end
+
+fun print_usage do print "Usage: json input.json"
+
+if args.length == 1 then
+ var input_path = args.first
+ var input_file = new IFStream.open( input_path )
+ var input_text = input_file.read_all
+ input_file.close
+
+ input_text.parse_and_display
+else
+ var s = "\{\"int\":1234, \"float\":0.1234, \"str\":\"str\", \"null\":null\}"
+ s.parse_and_display
+
+ s = "\{\"arr\":[1,2,3], \"obj\":\{\"int\":123, \"float\":-234.45\}\}"
+ s.parse_and_display
+
+ s = "\{\"arr\":[1,2.3,null,\"str\"], \"obj\":\{\"int\":123, \"float\":-234.45\}\}"
+ s.parse_and_display
+end