Note that in the previous post, the Person
struct was converted into a class
for testing purposes. From this point on Person
is a struct again unless specified otherwise.
One of the final things missing before our serialiser can reach a “minimalistic but useable” state is the ability to serialise both dynamic and associative arrays. Static arrays are saved as an excercise for this post.
I’ve already covered the majority of the main metaprogramming features that’ll be used in this post, and arrays are relatively simple to serialise, so this post will be on the shorter end.
As usual, here’s our current serialise function for reference:
For dynamic arrays we need to iterate over the array’s elements; serialise them, and then append the serialised value into a JSON array.
There’s not too much to explain about to code, so I’ll quickly highlight two things:
We use std.traits#isDynamicArray to check if T
is a dynamic array.
Creating a std.json#JSONValue that is also an array is a bit iffy, using parseJSON("[]")
was the cleanest way I could find.
(std.json is pretty outdated)
Do note that string
in D is actually just an immutable(char)[]
, which
would satisfy the std.json#isDynamicArray template.
This isn’t so much an issue in our case due to the fact we handle string
higher
up in the if-else chain, but it’s something worth keeping in mind.
Also, there’s actually two other string types in D, wstring
and dstring
.
While up to this point I’ve tried to pretend they don’t exist this series still won’t be going over
using them due to various reasons (such as std.json#JSONValue not supporting them).
In regards to that issue it may be wise to combine std.json#isDynamicArray with a check to make sure
the type isn’t a wstring
or dstring
, depending on your circumstances.
Other than that, there’s not really any other surprises in this code that haven’t been seen before - unless you’re using a super large dataset that causes a bunch of recursive calls that is… so onto deserialising!
Reference:
Again, there’s nothing overly new or complicated about the deserialisation code except for one thing:
std.range#ElementType is used to get the type of data stored in the array. Make sure to import std.range;
somewhere.
As another side note about strings, since they’re kind of annoying, ElementType
will always return dchar
if used on any kind of string. However ElementEncodingType
will properly return char
, wchar
, and dchar
for their respective
string types.
Finally, let’s give it a test:
As a common theme with this post there’s nothing new to explain for AAs, so here’s a quick list of noteworthy templates that we’re going to use:
std.traits#isAssociativeArray to check if a type is an AA.
std.traits#KeyType and std.traits#ValueType are used to get what type is used for the AA’s key and value, respectively.
We’ll use static assert
to enforce that the key type is a string.
And of course we should probably test these additions.
This post was a bit short and sweet. There weren’t really any new features to explain, mostly just new templates such as std.json#isDynamicArray.
While this post may have been a bit boring, hopefully the next post, where we explore the use of UDAs (User Defined Attributes) to allow deeper customisation of how things are serialised, will be more interesting.
The main two things you’ll need for this are:
std.traits#isStaticArray to determine whether a type is a static array or not.
After you identify a type (T
) as a static array, you can then be assured that the type will
have a constant property called T.length
, which of course is the length of the array.
Something to consider is, what if during deserialisation you find that the JSON data has either too many or too little values for the array?
For the purposes of this excercise (you may want to do something different for real-world usage):
If there are too many values, throw an exception.
If there are not enough values, fill the empty spaces up with either
[T.init(https://dlang.org/spec/property.html#init) (for value types),
or null
(for reference types).
And finally, here’s a test case: