Skip to content

Commit 7c8ef82

Browse files
committed
refactor(mcl/utils/json): Refactor and format
1 parent a2c3a5b commit 7c8ef82

File tree

2 files changed

+139
-95
lines changed

2 files changed

+139
-95
lines changed

packages/mcl/src/src/mcl/utils/json.d

Lines changed: 138 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,161 +1,183 @@
11
module mcl.utils.json;
22
import mcl.utils.test;
33
import mcl.utils.string;
4-
import std.traits: isNumeric, isArray, isSomeChar, ForeachType, isBoolean, isAssociativeArray;
5-
import std.json: JSONValue, JSONOptions, JSONType;
6-
import std.conv: to;
7-
import std.string: strip;
8-
import std.range: front;
9-
import std.stdio: writeln;
10-
import std.algorithm: map;
11-
import std.array: join, array, replace, split;
12-
import std.datetime: SysTime;
13-
import std.sumtype: SumType, isSumType;
14-
import core.stdc.string: strlen;
4+
import std.traits : isNumeric, isArray, isSomeChar, ForeachType, isBoolean, isAssociativeArray;
5+
import std.json : JSONValue, JSONOptions, JSONType;
6+
import std.conv : to;
7+
import std.string : strip;
8+
import std.range : front;
9+
import std.stdio : writeln;
10+
import std.algorithm : map;
11+
import std.array : join, array, replace, split;
12+
import std.datetime : SysTime;
13+
import std.sumtype : SumType, isSumType;
14+
import core.stdc.string : strlen;
15+
16+
string jsonValueToString(in JSONValue value)
17+
{
18+
return value.toString(JSONOptions.doNotEscapeSlashes).strip("\"");
19+
}
1520

1621
bool tryDeserializeJson(T)(in JSONValue value, out T result)
1722
{
18-
try {
23+
try
24+
{
1925
result = value.fromJSON!T;
2026
return true;
21-
} catch (Exception e) {
27+
}
28+
catch (Exception e)
29+
{
2230
return false;
2331
}
2432
}
2533

26-
T fromJSON(T)(in JSONValue value) {
27-
if (value.isNull) {
28-
return T.init;
29-
}
30-
static if (is(T == JSONValue)) {
31-
return value;
32-
}
33-
else static if (is(T == bool) || is(T == string) || isSomeChar!T || isNumeric!T || is(T == enum)) {
34-
return value.toString(JSONOptions.doNotEscapeSlashes).strip("\"").to!T;
35-
}
36-
else static if (isSumType!T) {
37-
static foreach (SumTypeVariant; T.Types)
38-
{{
39-
SumTypeVariant result;
40-
if (tryDeserializeJson!SumTypeVariant(value, result)) {
41-
return T(result);
42-
}
43-
}}
34+
T fromJSON(T)(in JSONValue value)
35+
{
36+
T result;
37+
if (value.isNull)
38+
result = T.init;
4439

45-
throw new Exception("Failed to deserialize JSON value");
46-
}
47-
else static if (isArray!T) {
48-
static if ( isBoolean!(ForeachType!T)) {
49-
if (value.type == JSONType.string && isBoolean!(ForeachType!T)) {
50-
return value.str.map!(a => a == '1').array;
40+
static if (is(T == JSONValue))
41+
result = value;
42+
else static if (is(T == bool) || is(T == string) || isSomeChar!T || isNumeric!T || is(T == enum))
43+
result = jsonValueToString(value).to!T;
44+
else static if (isSumType!T)
45+
{
46+
bool sumTypeDecoded = false;
47+
static foreach (SumTypeVariant; T.Types)
48+
{
49+
{
50+
SumTypeVariant sumTypeResult;
51+
if (tryDeserializeJson!SumTypeVariant(value, sumTypeResult))
52+
{
53+
sumTypeDecoded = true;
54+
result = sumTypeResult;
55+
}
5156
}
5257
}
53-
54-
if (value.type != JSONType.array) {
55-
return [value.fromJSON!(ForeachType!T)];
58+
if (!sumTypeDecoded)
59+
throw new Exception("Failed to deserialize JSON value");
60+
}
61+
else static if (isArray!T)
62+
{
63+
static if (isBoolean!(ForeachType!T))
64+
{
65+
if (value.type == JSONType.string && isBoolean!(ForeachType!T))
66+
result = value.str.map!(a => a == '1').array;
5667
}
68+
if (value.type != JSONType.array)
69+
result = [value.fromJSON!(ForeachType!T)];
70+
else
71+
result = value.array.map!(a => a.fromJSON!(ForeachType!T)).array;
5772

58-
return value.array.map!(a => a.fromJSON!(ForeachType!T)).array;
5973
}
60-
else static if (is(T == SysTime)) {
61-
return SysTime.fromISOExtString(value.toString(JSONOptions.doNotEscapeSlashes).strip("\""));
74+
else static if (is(T == SysTime))
75+
{
76+
result = SysTime.fromISOExtString(jsonValueToString(value));
6277
}
63-
else static if (is(T == struct)) {
64-
T result;
65-
static foreach (idx, field; T.tupleof) {
66-
if ((__traits(identifier, field).replace("_", "") in value.object) && !value[__traits(identifier, field).replace("_", "")].isNull) {
67-
result.tupleof[idx] = value[__traits(identifier, field).replace("_", "")].fromJSON!(typeof(field));
78+
else static if (is(T == struct))
79+
{
80+
static foreach (idx, field; T.tupleof)
81+
{
82+
if ((__traits(identifier, field).replace("_", "") in value.object) && !value[__traits(identifier, field)
83+
.replace("_", "")].isNull)
84+
{
85+
result.tupleof[idx] = value[__traits(identifier, field)
86+
.replace("_", "")].fromJSON!(typeof(field));
6887
}
6988
}
70-
return result;
7189
}
72-
else static if (isAssociativeArray!T) {
73-
T result;
74-
foreach (key, val; value.object) {
75-
if (key in result) {
90+
else static if (isAssociativeArray!T)
91+
{
92+
foreach (key, val; value.object)
93+
{
94+
if (key in result)
7695
result[key] = val.fromJSON!(typeof(result[key]));
77-
}
7896
}
79-
return result;
80-
}
81-
else {
82-
static assert(false, "Unsupported type: `", T, "` ", isSumType!T);
8397
}
98+
else
99+
static assert(false, "Unsupported type: `", T, "` ", isSumType!T);
100+
return result;
84101

85102
}
86103

87104
@("fromJSON")
88-
unittest {
105+
unittest
106+
{
89107
auto x = fromJSON!(SumType!(int, string))(JSONValue("1"));
90108
auto y = fromJSON!(SumType!(int, string))(JSONValue(1));
91109
}
92110

93111
JSONValue toJSON(T)(in T value, bool simplify = false)
94112
{
113+
JSONValue result;
95114
static if (is(T == enum))
96-
{
97-
return JSONValue(value.enumToString);
98-
}
115+
result = JSONValue(value.enumToString);
99116
else static if (is(T == bool) || is(T == string) || isSomeChar!T || isNumeric!T)
100-
return JSONValue(value);
101-
else static if ((isArray!T && isSomeChar!(ForeachType!T)) ) {
102-
return JSONValue(value.idup[0..(strlen(value.ptr)-1)]);
103-
}
117+
result = JSONValue(value);
118+
else static if ((isArray!T && isSomeChar!(ForeachType!T)))
119+
result = JSONValue(value.idup[0 .. (strlen(value.ptr) - 1)]);
104120
else static if (isArray!T)
105121
{
106122
if (simplify && value.length == 1)
107-
return value.front.toJSON(simplify);
108-
else if (simplify && isBoolean!(ForeachType!T) ) {
109-
static if (isBoolean!(ForeachType!T)) {
110-
return JSONValue((value.map!(a => a ? '1' : '0').array).to!string);
111-
}
112-
else {assert(0);}
123+
result = value.front.toJSON(simplify);
124+
else if (simplify && isBoolean!(ForeachType!T))
125+
{
126+
static if (isBoolean!(ForeachType!T))
127+
result = JSONValue((value.map!(a => a ? '1' : '0').array).to!string);
128+
else
129+
assert(0);
113130
}
114-
else {
115-
JSONValue[] result;
131+
else
132+
{
133+
JSONValue[] arrayResult;
116134
foreach (elem; value)
117-
result ~= elem.toJSON(simplify);
118-
return JSONValue(result);
135+
arrayResult ~= elem.toJSON(simplify);
136+
result = JSONValue(arrayResult);
119137
}
120138
}
121-
else static if (is(T == SysTime)) {
122-
return JSONValue(value.toISOExtString());
123-
}
139+
else static if (is(T == SysTime))
140+
result = JSONValue(value.toISOExtString());
124141
else static if (is(T == struct))
125142
{
126-
JSONValue[string] result;
143+
JSONValue[string] structResult;
127144
auto name = "";
128145
static foreach (idx, field; T.tupleof)
129146
{
130147
name = __traits(identifier, field).strip("_");
131-
result[name] = value.tupleof[idx].toJSON(simplify);
148+
structResult[name] = value.tupleof[idx].toJSON(simplify);
132149
}
133-
return JSONValue(result);
150+
result = JSONValue(structResult);
134151
}
135152
else
136153
static assert(false, "Unsupported type: `" ~ __traits(identifier, T) ~ "`");
154+
155+
return result;
156+
137157
}
138158

139-
version(unittest)
159+
version (unittest)
140160
{
141161
enum TestEnum
142162
{
143-
@StringRepresentation("supercalifragilisticexpialidocious")
144-
a,
163+
@StringRepresentation("supercalifragilisticexpialidocious") a,
145164
b,
146165
c
147166
}
167+
148168
struct TestStruct
149169
{
150170
int a;
151171
string b;
152172
bool c;
153173
}
174+
154175
struct TestStruct2
155176
{
156177
int a;
157178
TestStruct b;
158179
}
180+
159181
struct TestStruct3
160182
{
161183
int a;
@@ -166,18 +188,40 @@ version(unittest)
166188
@("toJSON")
167189
unittest
168190
{
169-
import std.stdio: writeln;
191+
import std.stdio : writeln;
192+
170193
assert(1.toJSON == JSONValue(1));
171194
assert(true.toJSON == JSONValue(true));
172195
assert("test".toJSON == JSONValue("test"));
173196
assert([1, 2, 3].toJSON == JSONValue([1, 2, 3]));
174197
assert(["a", "b", "c"].toJSON == JSONValue(["a", "b", "c"]));
175-
assert([TestEnum.a, TestEnum.b, TestEnum.c].toJSON == JSONValue(["supercalifragilisticexpialidocious", "b", "c"]));
176-
TestStruct testStruct = { 1, "test", true };
177-
assert(testStruct.toJSON == JSONValue(["a": JSONValue(1), "b": JSONValue("test"), "c": JSONValue(true)]));
178-
TestStruct2 testStruct2 = { 1, testStruct };
179-
assert(testStruct2.toJSON == JSONValue(["a": JSONValue(1), "b": JSONValue(["a": JSONValue(1), "b": JSONValue("test"), "c": JSONValue(true)])]));
180-
TestStruct3 testStruct3 = { 1, testStruct2 };
181-
assert(testStruct3.toJSON == JSONValue(["a": JSONValue(1), "b": JSONValue(["a": JSONValue(1), "b": JSONValue(["a": JSONValue(1), "b": JSONValue("test"), "c": JSONValue(true)])])]));
198+
assert([TestEnum.a, TestEnum.b, TestEnum.c].toJSON == JSONValue(
199+
["supercalifragilisticexpialidocious", "b", "c"]));
200+
TestStruct testStruct = {1, "test", true};
201+
assert(testStruct.toJSON == JSONValue([
202+
"a": JSONValue(1),
203+
"b": JSONValue("test"),
204+
"c": JSONValue(true)
205+
]));
206+
TestStruct2 testStruct2 = {1, testStruct};
207+
assert(testStruct2.toJSON == JSONValue([
208+
"a": JSONValue(1),
209+
"b": JSONValue([
210+
"a": JSONValue(1),
211+
"b": JSONValue("test"),
212+
"c": JSONValue(true)
213+
])
214+
]));
215+
TestStruct3 testStruct3 = {1, testStruct2};
216+
assert(testStruct3.toJSON == JSONValue([
217+
"a": JSONValue(1),
218+
"b": JSONValue([
219+
"a": JSONValue(1),
220+
"b": JSONValue([
221+
"a": JSONValue(1),
222+
"b": JSONValue("test"),
223+
"c": JSONValue(true)
224+
])
225+
])
226+
]));
182227
}
183-

packages/mcl/test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
#!/usr/bin/env sh
22
#export LD_DEBUG=all
33
export LD_LIBRARY_PATH=$(nix eval --raw nixpkgs#curl.out.outPath)/lib:$LD_LIBRARY_PATH
4-
dub test -- -e 'coda|fetchJson'
4+
dub test --build="unittest" -- -e 'coda|fetchJson'

0 commit comments

Comments
 (0)