Compare commits

...

11 Commits

Author SHA1 Message Date
Tristan B. Velloza Kildaire d99bfbaf35 Fix 2023-06-28 16:59:22 +02:00
Tristan B. Velloza Kildaire 2df7d833cf Make protected 2023-06-28 16:58:48 +02:00
Tristan B. Velloza Kildaire 1480a5afca - Updated example 2023-06-28 16:54:15 +02:00
Tristan B. Velloza Kildaire 73caebc501 Deserializer
- Ensure animal is right
2023-06-28 16:50:38 +02:00
Tristan B. Velloza Kildaire f7d9aee319 - Updated example in README 2023-06-28 16:50:30 +02:00
Tristan B. Velloza Kildaire c0bd2d624e Serializer
- Cleaned up

Deserializer

- Cleaned up
2023-06-28 16:44:00 +02:00
Tristan B. Velloza Kildaire b66c7741af Deserializer
- Cleaned up
- Removed now-completed comments
2023-06-28 16:21:30 +02:00
Tristan B. Velloza Kildaire ea079bbde4 Deserializer
- Added enum deserialization support
2023-06-28 12:25:39 +02:00
Tristan B. Velloza Kildaire 47b2a318da Package
- Documented public import

Exceptions

- Documented module and classes
2023-06-28 11:56:01 +02:00
Tristan B. Velloza Kildaire a15e0b5bcb Serializer
- Cleaned up
2023-06-28 11:55:09 +02:00
Tristan B. Velloza Kildaire dad7e04ccf Exceptions
- Added `DeserializationError`

Deserializer

- On error now throws `DeserializationError` exception
2023-06-28 11:51:57 +02:00
5 changed files with 156 additions and 39 deletions

View File

@ -22,6 +22,17 @@ struct Person
public int age;
public string[] list;
public JSONValue extraJSON;
public EnumType eType;
}
```
Our enum is defined as:
```d
enum EnumType
{
DOG,
CAT
}
```
@ -34,6 +45,7 @@ p1.lastname = "Kildaire";
p1.age = 23;
p1.list = ["1", "2", "3"];
p1.extraJSON = parseJSON(`{"item":1, "items":[1,2,3]}`);
p1.eType = EnumType.CAT;
```
Now, we make a call to `serializeRecord` as follows:
@ -47,6 +59,7 @@ This returns the following JSON:
```json
{
"age": 23,
"eType": "CAT",
"extraJSON": {
"item": 1,
"items": [
@ -57,7 +70,11 @@ This returns the following JSON:
},
"firstname": "Tristan",
"lastname": "Kildaire",
"list": ["1", "2", "3"]
"list": [
"1",
"2",
"3"
]
}
```
@ -76,6 +93,8 @@ struct Person
public bool[] list2;
public float[] list3;
public double[] list4;
public string[] list5;
public EnumType animal;
}
```
@ -91,7 +110,9 @@ Now, let's say we were given the following JSON:
"list": [1,2,3],
"list2": [true, false],
"list3": [1.5, 1.4],
"list4": [1.5, 1.4]
"list4": [1.5, 1.4],
"list5": ["baba", "booey"],
"animal": "CAT"
}
```
@ -108,7 +129,9 @@ JSONValue json = parseJSON(`{
"list": [1,2,3],
"list2": [true, false],
"list3": [1.5, 1.4],
"list4": [1.5, 1.4]
"list4": [1.5, 1.4],
"list5": ["baba", "booey"],
"animal": "CAT"
}
`);
@ -125,7 +148,7 @@ writeln(person):
Which will output:
```
Person("Tristan", "Kildaire", 23, true, {"bruh":1}, [1, 2, 3], [true, false], [1.5, 1.4], [1.5, 1.4])
Person("Tristan", "Kildaire", 23, true, {"bruh":1}, [1, 2, 3], [true, false], [1.5, 1.4], [1.5, 1.4], ["baba", "booey"], CAT)
```
## Installing
@ -141,9 +164,3 @@ And then in your D program import as follows:
```d
import jstruct;
```
## Help wanted
There are some outstanding issues I want to be able to fix/have implemented, namely:
- [ ] Support for custom types serialization/deserialization (think `enums` for example) - see issue #2

View File

@ -4,8 +4,9 @@
module jstruct.deserializer;
import std.json;
import jstruct.exceptions : SerializationError;
import std.traits : FieldTypeTuple, FieldNameTuple, isArray;
import jstruct.exceptions : DeserializationError;
import std.traits : FieldTypeTuple, FieldNameTuple, isArray, ForeachType, EnumMembers, fullyQualifiedName;;
import std.conv : to;
/**
* Deserializes the provided JSON into a struct of type RecordType
@ -103,13 +104,8 @@ public RecordType fromJSON(RecordType)(JSONValue jsonIn)
pragma(msg,"record."~structNames[cnt]);
}
}
//FIXME: Not sure how to get array support going, very new to meta programming
// FIXME: Add component type checking
else static if(isArray!(structTypes[cnt]))
{
import std.traits : ForeachType;
import std.conv : to;
alias recordArrayComponent = mixin("record."~structNames[cnt]);
JSONValue[] jsonArray = jsonIn[structNames[cnt]].array();
@ -179,6 +175,32 @@ public RecordType fromJSON(RecordType)(JSONValue jsonIn)
pragma(msg,"record."~structNames[cnt]);
}
}
else static if(is(structTypes[cnt] == enum))
{
string enumChoice = jsonIn[structNames[cnt]].str();
alias members = EnumMembers!(structTypes[cnt]);
version(dbg)
{
import std.stdio : writeln;
}
static foreach(member; members)
{
version(dbg)
{
writeln(member);
writeln(fullyQualifiedName!(member));
writeln(__traits(identifier, member));
}
if(__traits(identifier, member) == enumChoice)
{
mixin("record."~structNames[cnt]) = member;
}
}
}
else
{
// throw new
@ -186,13 +208,16 @@ public RecordType fromJSON(RecordType)(JSONValue jsonIn)
debug(dbg)
{
pragma(msg, "Unknown type for de-serialization");
pragma(msg, is(structTypes[cnt] == enum));
}
}
}
catch(JSONException e)
{
// TOOD: Should be DEserialization error
throw new SerializationError();
throw new DeserializationError();
}
}
@ -205,8 +230,11 @@ public RecordType fromJSON(RecordType)(JSONValue jsonIn)
*/
unittest
{
import std.string : cmp;
import std.stdio : writeln;
enum EnumType
{
DOG,
CAT
}
struct Person
{
@ -219,6 +247,7 @@ unittest
public float[] list3;
public double[] list4;
public string[] list5;
public EnumType animal;
}
JSONValue json = parseJSON(`{
@ -231,7 +260,8 @@ unittest
"list2": [true, false],
"list3": [1.5, 1.4],
"list4": [1.5, 1.4],
"list5": ["baba", "booey"]
"list5": ["baba", "booey"],
"animal": "CAT"
}
`);
@ -239,7 +269,7 @@ unittest
debug(dbg)
{
writeln(person);
writeln("Deserialized as: ", person);
}
assert(cmp(person.firstname, "Tristan") == 0);
@ -252,18 +282,25 @@ unittest
assert(person.list3 == [1.5F, 1.4F]);
assert(person.list4 == [1.5, 1.4]);
assert(person.list5 == ["baba", "booey"]);
assert(person.animal == EnumType.CAT);
}
version(unittest)
{
import std.string : cmp;
import std.stdio : writeln;
}
/**
* Another example deserialization of JSON
* to our `Person` struct
* to our `Person` struct but here there
* is a problem with deserialization as
* there is a missing field `isMale`
* in the provided JSON
*/
unittest
{
import std.string : cmp;
import std.stdio : writeln;
struct Person
{
public string firstname, lastname;
@ -271,6 +308,7 @@ unittest
public bool isMale;
public JSONValue obj;
public int[] list;
}
JSONValue json = parseJSON(`{
@ -287,9 +325,47 @@ unittest
Person person = fromJSON!(Person)(json);
assert(false);
}
catch(SerializationError)
catch(DeserializationError)
{
assert(true);
}
}
unittest
{
enum EnumType
{
DOG,
CAT
}
struct Person
{
public string firstname, lastname;
public EnumType animal;
}
JSONValue json = parseJSON(`{
"firstname" : "Tristan",
"lastname": "Kildaire",
"animal" : "CAT"
}
`);
try
{
Person person = fromJSON!(Person)(json);
writeln(person);
assert(true);
}
catch(DeserializationError)
{
assert(false);
}
}

View File

@ -1,5 +1,11 @@
/**
* Exception types
*/
module jstruct.exceptions;
/**
* General exception type
*/
public abstract class JStructException : Exception
{
this(string msg)
@ -8,6 +14,9 @@ public abstract class JStructException : Exception
}
}
/**
* Error on serialization
*/
public final class SerializationError : JStructException
{
this()
@ -15,3 +24,14 @@ public final class SerializationError : JStructException
super("Error serializing");
}
}
/**
* Error on deserialization
*/
public final class DeserializationError : JStructException
{
this()
{
super("Error deserializing");
}
}

View File

@ -13,4 +13,7 @@ public import jstruct.serializer;
*/
public import jstruct.deserializer;
/**
* Exception types
*/
public import jstruct.exceptions;

View File

@ -34,9 +34,6 @@ public JSONValue serializeRecord(RecordType)(RecordType record)
// pragma(msg, structValues[cnt]);
}
import std.traits : isArray;
static if(__traits(isSame, structTypes[cnt], int))
{
builtJSON[structNames[cnt]] = structValues[cnt];
@ -68,7 +65,6 @@ public JSONValue serializeRecord(RecordType)(RecordType record)
else static if(isArray!(structTypes[cnt]))
{
builtJSON[structNames[cnt]] = structValues[cnt];
// pragma(msg, "WAIT", "d"~mixin(structTypes[cnt]));
}
else
{
@ -85,10 +81,13 @@ public JSONValue serializeRecord(RecordType)(RecordType record)
}
// Test serialization of a struct to JSON
private enum EnumType
version(unittest)
{
DOG,
CAT
import std.algorithm.searching : canFind;
import std.string : cmp;
import std.stdio : writeln;
}
/**
@ -97,10 +96,12 @@ private enum EnumType
*/
unittest
{
import std.algorithm.searching : canFind;
import std.string : cmp;
import std.stdio : writeln;
enum EnumType
{
DOG,
CAT
}
struct Person
{
public string firstname, lastname;