on master help sign in
Clean up the Json APIs. Permit conversion from JS strings to records.
commit8800fa30c0b1dca1a6db4c11d93a5e6737d7b418 authorevancz <info@elm-lang.org> dateSat 2 Mar 2013, 21:43 (14 years ago) parentc40d2e4
5 files changed+289−1
core/JavaScript.elm+40−1 core/Json/Dynamic.elm+76 core/Json/Static.elm+12 core/Native/JavaScript.js+76 core/Native/Json.js+85
core/JavaScript.elm+40−1
@@ -1,4 +1,43 @@
11
22module JavaScript where
33
4−toString = 4
4+import Native.JavaScript as JS
5+
6+-- To Elm
7+
8+toString : JSString -> String
9+toString = JS.toString
10+
11+toInt : JSNumber -> Int
12+toInt = JS.toInt
13+
14+toFloat : JSNumber -> Float
15+toFloat = JS.id
16+
17+toBool : JSBool -> Bool
18+toBool = JS.id
19+
20+toList : JSArray a -> [a]
21+toList = JS.toList
22+
23+toRecord = JS.toRecord
24+
25+
26+-- From Elm
27+
28+fromString : String -> JSString
29+fromString = JS.fromString
30+
31+fromInt : Int -> JSNumber
32+fromInt = JS.id
33+
34+fromFloat : Float -> JSNumber
35+fromFloat = JS.id
36+
37+fromBool : Bool -> JSBool
38+fromBool = JS.id
39+
40+fromList : [a] -> JSArray a
41+fromList = JS.fromList
42+
43+fromRecord = JS.fromRecord
core/Json/Dynamic.elmnew file+76
@@ -0,0 +1,76 @@
1+
2+module Json.Dynamic where
3+
4+import Dict
5+import JavaScript as JS
6+import Native.Json as Native
7+
8+
9+data Value
10+ = String String
11+ | Number Float
12+ | Boolean Bool
13+ | Null
14+ | Array [Value]
15+ | Object (Dict String Value)
16+
17+
18+-- String Converters
19+
20+toString : Value -> String
21+toString v = JS.toString (Native.toPrettyJSString "" v)
22+
23+toPrettyString : String -> Value -> String
24+toPrettyString sep v = JS.toString (Native.toPrettyJSString sep v)
25+
26+toJSString : Value -> JSString
27+toJSString v = Native.toPrettyJSString "" v
28+
29+fromString : String -> Maybe Value
30+fromString s = Native.fromJSString (JS.fromString s)
31+
32+fromJSString : JSString -> Maybe Value
33+fromJSString = Native.fromJSString
34+
35+
36+-- Extract Elm values from Json values
37+
38+string : String -> Value -> String
39+string base v = case v of { String s -> s ; _ -> base }
40+
41+number : Float -> Value -> Float
42+number base v = case v of { Number n -> n ; _ -> base }
43+
44+boolean : Bool -> Value -> Bool
45+boolean base v = case v of { Boolean b -> b ; _ -> base }
46+
47+array : [Value] -> Value -> [Value]
48+array base v = case v of { Array a -> a ; _ -> base }
49+
50+object : Dict String Value -> Value -> Dict String Value
51+object base v = case v of { Object o -> o ; _ -> base }
52+
53+
54+-- Extract Elm values from dictionaries of Json values
55+
56+find get =
57+ let f base key dict =
58+ case Dict.lookup key dict of
59+ Nothing -> base
60+ Just v -> get base v
61+ in f
62+
63+findString : String -> Dict String Value -> String
64+findString = find string
65+
66+findNumber : Float -> Dict String Value -> Float
67+findNumber = find number
68+
69+findBoolean : Bool -> Dict String Value -> Bool
70+findBoolean = find boolean
71+
72+findArray : [Value] -> Dict String Value -> [Value]
73+findArray = find array
74+
75+findObject : Dict String Value -> Dict String Value -> Dict String Value
76+findObject = find object
core/Json/Static.elmnew file+12
@@ -0,0 +1,12 @@
1+
2+module Json.Static where
3+
4+import JavaScript as JS
5+import Native.Json as Native
6+
7+fromJSString = Native.recordFromJSString
8+fromString s = Native.recordFromJSString (JS.fromString s)
9+
10+toString r = JS.toString (Native.recordToPrettyJSString "" r)
11+toPrettyString sep r = JS.toString (Native.recordToPrettyJSString sep r)
12+toJSString r = Native.recordToPrettyJSString "" r
core/Native/JavaScript.jsnew file+76
@@ -0,0 +1,76 @@
1+/**
2+module Native.JavaScript where
3+**/
4+
5+(function() {
6+ 'use strict';
7+
8+ var fromArray = Elm.Native.List.fromArray;
9+ var toArray = Elm.Native.List.toArray;
10+
11+ function fromJS(v) {
12+ var type = typeof v;
13+ if (type === 'number' ) return v;
14+ if (type === 'boolean') return v;
15+ if (type === 'string' ) return fromArray(v);
16+ if (v instanceof Array) {
17+ var arr = [];
18+ var len = v.length;
19+ for (var i = 0; i < len; ++i) {
20+ var x = fromJS(v[i]);
21+ if (x !== null) arr.push(x);
22+ }
23+ return fromArray(arr);
24+ }
25+ if (type === 'object') {
26+ var rec = { _:{} };
27+ for (var f in v) {
28+ var x = fromJS(v[f]);
29+ if (x !== null) rec[f] = x;
30+ }
31+ return rec;
32+ }
33+ return null;
34+ }
35+
36+ function toJS(v) {
37+ var type = typeof v;
38+ if (type === 'number' || type === 'boolean') return v;
39+ if (type === 'object' && '_' in v) {
40+ var obj = {};
41+ for (var k in v) {
42+ var x = v[k];
43+ if (x !== null) obj[k] = x;
44+ }
45+ return obj;
46+ }
47+ if (type === 'object' && (v.ctor === 'Cons' || v.ctor === 'Nil')) {
48+ var array = toArray(v);
49+ for (var i = array.length; i--; ) {
50+ array[i] = toJS(array[i]);
51+ }
52+ if (typeof array[0] === 'string') array.join('');
53+ return array;
54+ }
55+ return null;
56+ }
57+
58+ function fromRecord(r) {
59+ if (typeof r === 'object' && '_' in r) {
60+ return toJS(r);
61+ }
62+ throw new Error("'fromRecord' must be called on a record.");
63+ }
64+
65+ Elm.Native.JavaScript = {
66+ id : function(n) { return n },
67+ toInt : function(n) { return n|0 },
68+ toString : function(s) { return fromArray(s) },
69+ toList : fromArray,
70+ fromString : function(s) { return toArray(s).join('') },
71+ fromList : toArray,
72+ toRecord : fromJS,
73+ fromRecord : fromRecord
74+ };
75+
76+}());
core/Native/Json.jsnew file+85
@@ -0,0 +1,85 @@
1+
2+/**
3+module Native.Json where
4+
5+import Maybe
6+import JavaScript
7+import Dict
8+import List
9+**/
10+
11+(function() {
12+ 'use strict';
13+
14+ var JS = Elm.JavaScript;
15+
16+ function fromValue(v) {
17+ switch (v.ctor) {
18+ case 'Null' : return null;
19+ case 'String' : return JS.fromString(v._0);
20+ case 'Object' :
21+ var obj = {};
22+ var array = JS.fromList(Elm.Dict.toList(v._0));
23+ for (var i = arr.length; i--; ) {
24+ obj[JS.fromString(array[i]._0)] = fromValue(array[i]._1);
25+ }
26+ return obj;
27+ case 'Array' :
28+ var array = JS.fromList(v._0);
29+ for (var i = array.length; i--; ) {
30+ array[i] = fromValue(array[i]);
31+ }
32+ return array;
33+ default :
34+ return v._0;
35+ }
36+ }
37+
38+ function toPrettyJSString(sep, obj) {
39+ return JSON.stringify(fromValue(obj), null, JS.fromString(sep));
40+ }
41+
42+ function toValue(v) {
43+ switch (typeof v) {
44+ case 'string' : return { ctor:"String", _0: JS.toString(v) };
45+ case 'number' : return { ctor:"Number", _0: JS.toFloat(v) };
46+ case 'boolean': return { ctor:"Bool" , _0: JS.toBool(v) };
47+ case 'object' :
48+ if (v === null) return { ctor:"Null" };
49+ if (v instanceof Array) {
50+ for (var i = v.length; i--; ) { v[i] = toValue(v[i]); }
51+ return { ctor:"Array", _0: JS.toList(v) };
52+ }
53+ var array = [];
54+ for (var k in v) array.push(Tuple2(JS.toString(k), toValue(v[k])));
55+ return { ctor:"Object", _0: Elm.Dict.fromList(JS.toList(array)) };
56+ }
57+ }
58+
59+ function fromJSString(str) {
60+ try {
61+ return Elm.Maybe.Just(toValue(JSON.parse(str)));
62+ } catch (e) {
63+ return Elm.Maybe.Nothing;
64+ }
65+ }
66+
67+ function recordFromJSString(str) {
68+ try {
69+ return Elm.Maybe.Just(JS.toRecord(JSON.parse(str)));
70+ } catch (e) {
71+ return Elm.Maybe.Nothing;
72+ }
73+ }
74+ function recordToPrettyJSString(sep, rec) {
75+ return JSON.stringify(JS.fromRecord(rec), null, JS.fromString(sep));
76+ }
77+
78+ Elm.Native.Json = {
79+ toPrettyJSString : F2(toPrettyJSString),
80+ fromJSString : fromJSString,
81+ recordToPrettyJSString : F2(recordToPrettyJSString),
82+ recordFromJSString : recordFromJSString
83+ };
84+
85+}());