Thread overview
compile time introspection and code generation - automatically serialize to json
Jul 21, 2011
Tobias Pankrath
Jul 21, 2011
Robert Clipsham
Jul 21, 2011
Robert Clipsham
Jul 21, 2011
Jacob Carlborg
Jul 21, 2011
Tobias Pankrath
Jul 21, 2011
Jacob Carlborg
Jul 21, 2011
Adam Ruppe
July 21, 2011
Hi everyone,

I'm taking a look at D again and asked myself, if
it is possible to write a template mixin or something
similiar that automatically serializes an object to json.

For example:

class MyClass
{
    string memberA;
    int memberB;
    MyClass memberC;
    mixin ToJson!MyClass;
}

should make possible to automatically output
"someid" { "memberA" : "somestring",
	"memberB" : 12,
	memberC : "someotherid"};

How could this be accomplished? I've found std.traits
RepresentationTypeTupel but don't see how this would
help me.

Thanks,

Tobias


July 21, 2011
On 21/07/2011 08:57, Tobias Pankrath wrote:
> Hi everyone,
>
> I'm taking a look at D again and asked myself, if
> it is possible to write a template mixin or something
> similiar that automatically serializes an object to json.
>
> For example:
>
> class MyClass
> {
>      string memberA;
>      int memberB;
>      MyClass memberC;
>      mixin ToJson!MyClass;
> }
>
> should make possible to automatically output
> "someid" { "memberA" : "somestring",
> 	"memberB" : 12,
> 	memberC : "someotherid"};
>
> How could this be accomplished? I've found std.traits
> RepresentationTypeTupel but don't see how this would
> help me.
>
> Thanks,
>
> Tobias
>
>

Something like this is very possible, here's a start for you (untested, sorry about the awkward indentation):

----
mixin template ToJson(T)
{
  string toJson()
  {
    foreach (i, member; T.tupleof)
    {
        enum memberName = T.tupleof[i].stringof[
				T.stringof.length + 3 .. $
				];
        writefln("%s : %s", memberName, member);
    }
    assert(0, "Eventually this should return a json string, "
              "but for now it just asserts");
  }
}
someInstanceOfMyClass.toJson();
----

I'll leave it at this and leave you to figure out the rest - just ask if you get stuck :)

-- 
Robert
http://octarineparrot.com/
July 21, 2011
On 21/07/2011 08:57, Tobias Pankrath wrote:
> Hi everyone,
>
> I'm taking a look at D again and asked myself, if
> it is possible to write a template mixin or something
> similiar that automatically serializes an object to json.
>
> For example:
>
> class MyClass
> {
>      string memberA;
>      int memberB;
>      MyClass memberC;
>      mixin ToJson!MyClass;
> }
>
> should make possible to automatically output
> "someid" { "memberA" : "somestring",
> 	"memberB" : 12,
> 	memberC : "someotherid"};
>
> How could this be accomplished? I've found std.traits
> RepresentationTypeTupel but don't see how this would
> help me.
>
> Thanks,
>
> Tobias
>
>

Side note: If/when you finish this, you should definitely make a pull request for phobos' std.json! This sort of thing would be incredibly useful!

-- 
Robert
http://octarineparrot.com/
July 21, 2011
On 2011-07-21 09:57, Tobias Pankrath wrote:
> Hi everyone,
>
> I'm taking a look at D again and asked myself, if
> it is possible to write a template mixin or something
> similiar that automatically serializes an object to json.
>
> For example:
>
> class MyClass
> {
>      string memberA;
>      int memberB;
>      MyClass memberC;
>      mixin ToJson!MyClass;
> }
>
> should make possible to automatically output
> "someid" { "memberA" : "somestring",
> 	"memberB" : 12,
> 	memberC : "someotherid"};
>
> How could this be accomplished? I've found std.traits
> RepresentationTypeTupel but don't see how this would
> help me.
>
> Thanks,
>
> Tobias

Have a look at Orange: http://www.dsource.org/projects/orange
I'm in a middle of a complete rewrite but you can use a previous version (if it still works) or look at the code.

-- 
/Jacob Carlborg
July 21, 2011
> 
> Have a look at Orange: http://www.dsource.org/projects/orange
> I'm in a middle of a complete rewrite but you can use a previous version
> (if it still works) or look at the code.
> 
Thank you for pointing me there. Looks very interesting. I took a quick look at the code and got some questions. I found this pattern quite often in phobos sources, too.

Why do you declare in Reflection.d[1] a template parameterNamesOf(alias func) and one called parameterNamesOfImpl? Wouldn't be one sufficient?

I do understand the case if you want to use the template recursively and
hide one parameter like in fieldsOf / fieldsOfImpl.
Though I don't understand why you are using a recursive template in fieldsOf
and a imperative function in parameterNamesOfImpl? Is it possible to you use
both in both places?



[1] http://www.dsource.org/projects/orange/browser/orange/util/Reflection.d
July 21, 2011
For another implementation, find the functions toJson and toJsonValue in my web.d

http://arsdnet.net/dcode/web.d


Bascially: foreach(member; item.tupleof) {
   static if(is(typeof(member) == something)
     json it
   else static if.... repeat for supported type families
}
July 21, 2011
On 2011-07-21 13:09, Tobias Pankrath wrote:
>>
>> Have a look at Orange: http://www.dsource.org/projects/orange
>> I'm in a middle of a complete rewrite but you can use a previous version
>> (if it still works) or look at the code.
>>
> Thank you for pointing me there. Looks very interesting. I took a quick look
> at the code and got some questions. I found this pattern quite often in
> phobos sources, too.
>
> Why do you declare in Reflection.d[1] a template
> parameterNamesOf(alias func) and one called parameterNamesOfImpl? Wouldn't
> be one sufficient?
>
> I do understand the case if you want to use the template recursively and
> hide one parameter like in fieldsOf / fieldsOfImpl.
> Though I don't understand why you are using a recursive template in fieldsOf
> and a imperative function in parameterNamesOfImpl? Is it possible to you use
> both in both places?
>
>
>
> [1] http://www.dsource.org/projects/orange/browser/orange/util/Reflection.d

The thought behind that was that I wanted to force the function to be used at compile time. But now when I think about it you could just declare the argument as a template argument on the regular function.

-- 
/Jacob Carlborg