RejectedSoftware Forums

Sign up

Deserializing nested json objects

Hi,

I have json payloads to process which are 80% similar. However, one field - let's say "animal" - is different in each case.

{
  "p": "some text",
  "n": 1234,
  "animal": { "age": 12, "name": "cat"}
}

Or sometimes as

{
  "p": "some text",
  "n": 1234,
  "animal": { "says": "bowwow", "name": "dog"}
}

What's a clean (and simple) way to deserialize this object? I was hoping to do this, but it fails:

struct MyResponse {
  string p;
  int n;
  Json animal;
}

auto res = deserializeJson!MyResponse(stringFromCurl);

I also tried a template, but I've had trouble getting the logic to flow. In one method I keep getting stuck with the compile error Error: variable r cannot be read at compile time

struct MyResponse(T) {
  string p;
  int n;
  T animal;
}

struct Cat {
  string name;
  int age;
}

auto res = deserializeJson!(MyResponse!Cat(stringFromCurl));

Re: Deserializing nested json objects

Error: variable r cannot be read at compile time

Correction - that's Error: variable stringFromCurl cannot be read at compile time

Re: Deserializing nested json objects

On Mon, 22 Jan 2018 23:47:28 GMT, Taylor Gronka wrote:

(...)

What's a clean (and simple) way to deserialize this object? I was hoping to do this, but it fails:

struct MyResponse {
   string p;
   int n;
   Json animal;
}

auto res = deserializeJson!MyResponse(stringFromCurl);

This kind of nesting is generally supported and, if the kind of animal is not known upfront, this is what I'd usually also do. What does the error message say?

I also tried a template, but I've had trouble getting the logic to flow. In one method I keep getting stuck with the compile error Error: variable r cannot be read at compile time

struct MyResponse(T) {
   string p;
   int n;
   T animal;
}

struct Cat {
   string name;
   int age;
}

auto res = deserializeJson!(MyResponse!Cat(stringFromCurl));

I this case the parenthesis are just a bit off:

auto res = deserializeJson!(MyResponse!Cat)(stringFromCurl);

should work as long as the exact type is known upfront. BTW, this could also be written like this to avoid the chained parenthesis and to make it slightly nicer to read: stringFromCurl.deserializeJson!(MyResponse!Cat)

Re: Deserializing nested json objects

This kind of nesting is generally supported and, if the kind of animal is not known upfront, this is what I'd usually also do. What does the error message say?

Thanks for the help! I found the issue was my mistake - for this testing, another Json field was returning as null, which was failing. There's a flag for ignoring null values when unpacking, right? How is that done (and where is it documented)?

I see something like Nullable!Json u in these forums, but I think that's deprecated now? I think I saw another flag such as @ignore... Something like

struct animal {
  string p;
  Nullable!Json animal;
  @ignore Json animal2;
}

Re: Deserializing nested json objects

Ah! I think I found it at
https://github.com/vibe-d/vibe.d/issues/1541

My actual code which seems to be working, for posterity:

struct BapiResponse {
	string p;  // Purpose
	string url;
	@optional FlashMessage[] flashmsgs;
	//Json flashmsgs;
	string status;
	string i;  // Info
	Json u;

}

Re: Deserializing nested json objects

Am 23.01.2018 um 19:13 schrieb Taylor Gronka:

This kind of nesting is generally supported and, if the kind of animal is not known upfront, this is what I'd usually also do. What does the error message say?

Thanks for the help! I found the issue was my mistake - for this testing, another Json field was returning as null, which was failing. There's a flag for ignoring null values when unpacking, right? How is that done (and where is it documented)?

I see something like Nullable!Json u in these forums, but I think that's deprecated now? I think I saw another flag such as @ignore... Something like

struct animal {
   string p;
   Nullable!Json animal;
   @ignore Json animal2;
}

Nullable!T is still supported and makes sense for non-reference types
(e.g. structs or numbers), or if the field should actually be forced to
contain null instead of just being omitted. But other than that, I'd
usually also go with @optional.

@ignore just completely ignores a field during the whole serialization
process, so that it always ends up empty after deserializeJson, no
matter if present in the input JSON or not.