Newbie: JSON string to anonymous object?

2,091 views
Skip to first unread message

NM

unread,
May 27, 2014, 7:36:23 PM5/27/14
to jay...@googlegroups.com
Hi,

  Is it possible to deserialize a JSON string (which may have nested JSON arrays of structures) to an anonymous object (which may have other corresponding anonymous objects or arrays of them)?

Thank in advance and regards

Atif Aziz

unread,
May 29, 2014, 2:49:51 AM5/29/14
to jay...@googlegroups.com
You can serialize anonymous types but deserialization is tougher. If not for anything, how do you imagine going about expressing the structure to deserialize without instantiating it first? You would have to provide some sort of dummy or prototype. Is that what you had in mind?

- Atif
--
You received this message because you are subscribed to the Google Groups "Jayrock" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jayrock+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Navin Mishra

unread,
Jun 11, 2014, 1:19:43 PM6/11/14
to jay...@googlegroups.com
Thanks. It makes sense. Is it possible to deserialize a JSON string (that has arrays and all) to a .NET dynamic object with the same corresponding structure (that is, array of dynamic objects and others)?

Thanks again and regards


From: Atif Aziz <aziz...@gmail.com>
To: "jay...@googlegroups.com" <jay...@googlegroups.com>
Sent: Wednesday, May 28, 2014 11:49 PM
Subject: Re: [Jayrock] Newbie: JSON string to anonymous object?

--
You received this message because you are subscribed to a topic in the Google Groups "Jayrock" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/jayrock/uOgU1Tr8b4o/unsubscribe.
To unsubscribe from this group and all its topics, send an email to jayrock+u...@googlegroups.com.

Atif Aziz

unread,
Jun 11, 2014, 6:18:34 PM6/11/14
to jay...@googlegroups.com
Yes you can. For example:

dynamic points = JsonConvert.Import("[{x:12,y:34},{x:56,y:78}]");

Console.WriteLine((int) points.Length);

dynamic pt = points[1];

Console.WriteLine("x = {0}, y = {1}", (int) pt.x, (int) pt.y);


- Atif

Navin Mishra

unread,
Jun 11, 2014, 6:24:32 PM6/11/14
to jay...@googlegroups.com
Thanks! Will it also work for more complex JSON say which contains an array of structures in which each element itself might be itself an array?

Thanks again and regards



Sent: Wednesday, June 11, 2014 3:18 PM
Subject: Re: [Jayrock] Newbie: JSON string to dynamic object?

Atif Aziz

unread,
Jun 11, 2014, 6:38:38 PM6/11/14
to jay...@googlegroups.com
Yes

Navin Mishra

unread,
Jun 11, 2014, 6:44:08 PM6/11/14
to jay...@googlegroups.com
Thanks for the quick response! Will try. I thought when I tried last it didn't seem to work but will try again. Specifically, it didn't seem to return the expected nested array of dynamic objects but I might be wrong.


Sent: Wednesday, June 11, 2014 3:38 PM

Atif Aziz

unread,
Jun 12, 2014, 1:04:55 AM6/12/14
to jay...@googlegroups.com
If it's not giving the expected results then post the example you're trying here & I might be able to help better.

- Atif

Navin Mishra

unread,
Jun 12, 2014, 1:43:19 PM6/12/14
to jay...@googlegroups.com
Thank you very much. Consider this JSON which has nested arrays:

           string strJSON =
           "{\"topic\":\"history\",\"msg\":\"test\",\"ts\":1402589852273,\"sq\":1123,\"req\":22,\"all\":[[\"rid\",\"cid\",\"rtype\",\"begin\",\"period\",\"tlbl\",\"note\",\"trunk\",\"aid\",\"aid-friendly\",\"secure\",\"extra\",\"people\",\"trail\",\"minf\",\"begin-local\",2090,\"00020000-0007-51a6-25ba-0010490cafd6\",2,1400173785238,6,1400173785238,\"\",\"\",\"\",\"\",false,\"\",[[\"lbl\",\"num\",\"num-canonical\"],[\"person2\",\"503\",\"503\"]],[[\"res\",\"period\",\"party-lbl\",\"party-num\",\"party2-lbl\",\"party2-num\"],[17,0,\"person2\",\"503\",\"JohnAppleseed\",\"501\"],[-3,6,\"person2\",\"503\",\"\",\"\"],[-2,6,\"\",\"\",\"\",\"\"]],{\"cid\":4153296634},1400148585238,2089,\"00020000-0005-51a6-25ba-0010490cafd6\",0,1400173737020,22,1400173737020,\"\",\"\",\"\",\"\",false,\"\",[[\"lbl\",\"num\",\"numS\"],[\"C\",\"502\",\"502\"]],[[\"res\",\"period\",\"party-lbl\",\"party-num\",\"party2-lbl\",\"party2-num\"],[17,0,\"JohnAppleseed\",\"501\",\"C\",\"502\"],[-2, 22,\"\",\"\",\"\",\"\"]],{\"cid\":26605976},1400148537020,2088,\"00020000-0004-51a6-25ba-0010490cafd6\",0,1400173613918,8,1400173613918,\"\",\"\",\"\",\"\",false,\"\",[[\"lbl\",\"num\",\"num-canonical\"],\"C\",\"502\",\"502\"]],[[\"res\",\"period\",\"party-lbl\",\"party-num\",\"party2-lbl\",\"party2-num\"],[17,0,\"JohnAppleseed\",\"501\",\"C\",\"502\"],[-3,8,\"C\",\"502\",\"\",\"\"],[-2,8,\"\",\"\",\"\",\"\"]],{\"cid\":110744295},1400148413918]]}";

Converting it to dynamic  using JsonConvert.Import(strJSON) gives a dynamic object with
Json.JsonObject in there. It has top level recs as a JsonArray but I was expecting a standard Array of dynamic objects. Basically, in the return I need to have dynamic objects with standard .NET types only and not any Jayrock specific types. The reason being I am using Jayrock inside a class library that takes care of JSON parsing using Jayrock and hides that implementation detail from the clients using the library. The client needs to see only dynamic objects which contain standard .NET objects, arrays and all.

Does that make sense and is it possible using Jayrock?

Thanks again and regards

Sent: Wednesday, June 11, 2014 10:04 PM

Atif Aziz

unread,
Jun 13, 2014, 1:51:05 AM6/13/14
to jay...@googlegroups.com
I understand your scenario but I think there's some terminology confusion to be sorted out first. What do you exactly mean or understand by standard “dynamic objects”? There is a protocol for dynamic programming via IDynamicMetaObjectProvider but that's the only standard type. Are you talking about ExpandoObject here by any chance? Also, dynamic binding is really a client decision. If you want to return an array of dynamics then you just do this:

JsonConvert.Import<dynamic[]>(strJSON);

- Atif

Navin Mishra

unread,
Jun 13, 2014, 5:20:26 PM6/13/14
to jay...@googlegroups.com
Thanks. Yes, I meant ExpandoObjects to which the given Json string - containing nested arrays of structures or not - need to be parsed to. Basically the returned Expando "dynamic" object is shaped according to the given Json however complex.

Is it possible using Jayock?

Thanks again and regards




Sent: Thursday, June 12, 2014 10:50 PM

Atif Aziz

unread,
Jun 20, 2014, 1:02:08 PM6/20/14
to jay...@googlegroups.com
You should know that when you do an “untyped” import, the types that Jayrock returns implement standard types. For example, JsonObject and JsonArray implement IDictionary and IList, respectively, including their generic counterparts IDictionary<string, object> and IList<string>. As a result, while you might be returning the concrete implementations, JsonObject and JsonArray, the user of library shouldn't have to care or know as long as they treat them (via casting) as standard dictionaries and lists. In any case, if you wish to have more control and still return a JSON object as ExpandoObject and a JSON array as object[], then I've posted a sample importer implementation as a gist that should give you exactly that:


- Atif


On Wed, Jun 11, 2014 at 7:16 PM, 'Navin Mishra' via Jayrock <jay...@googlegroups.com> wrote:

Navin Mishra

unread,
Sep 11, 2014, 7:08:15 PM9/11/14
to jay...@googlegroups.com
Hi,

  Is it possible to deserialize a JSON string which may have nested JSON arrays or structures to corresponding strongly typed object with the same structure (assuming the corresponding classes for each JSON structure are available)? Is there an example showing that?

Thanks and regards

NM

unread,
Sep 14, 2014, 8:58:39 AM9/14/14
to jay...@googlegroups.com

Any pointers in this regard?

Thanks!

Atif Aziz

unread,
Sep 17, 2014, 4:44:28 PM9/17/14
to jay...@googlegroups.com

NM

unread,
Sep 17, 2014, 8:12:44 PM9/17/14
to jay...@googlegroups.com
Thank you! I tried the sample. My json contains hyphens and those values are not serialized correctly and set to null. Is there a way around that probably similar to what is possible using the .NET DataContract attributes to define how json attributes with hyphens need to be mapped to C# class members? That is the missing piece now.

Thanks again and reahrds

Atif Aziz

unread,
Sep 18, 2014, 2:06:34 AM9/18/14
to jay...@googlegroups.com
Apply the JsonMemberName attribute to a property of a class to set its external name in JSON, like this:

class Thing { 
  [JsonMemberName("foo")] 
  string Bar { get;set; } 
};

- Atif

Navin Mishra

unread,
Sep 18, 2014, 2:14:53 PM9/18/14
to jay...@googlegroups.com
That works like a charm...awesome! Another thing, can a numeric value be automatically casted to a defined Enumeration as well and, if so, how?

Thanks again and regards


Sent: Wednesday, September 17, 2014 11:06 PM
Subject: Re: [Jayrock] JSON string to nested C# objects?

You received this message because you are subscribed to a topic in the Google Groups "Jayrock" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/jayrock/uOgU1Tr8b4o/unsubscribe.
To unsubscribe from this group and all its topics, send an email to jayrock+u...@googlegroups.com.

Atif Aziz

unread,
Sep 18, 2014, 4:59:37 PM9/18/14
to jay...@googlegroups.com
The default enum importer in Jayrock deliberately forbids importing enums from JSON numbers to avoid accidental and unintended effects. To do so nonetheless, you can write your own custom importer. I've posted an example (and attached it) that demonstrates importing enums from JSON numbers or strings. For strings, it delegates to the EnumImporter implementation already found in Jayrock.

- Atif
Program.cs

Navin Mishra

unread,
Sep 19, 2014, 8:56:54 AM9/19/14
to jay...@googlegroups.com
Thank you. How to do this automatically when an object (or nested objects within) contains enums of different types? Something like:


class Thing { 
  [JsonMemberName("member-1")] 
  EnumType1 member1 { get;set; }

 

[JsonMemberName("member-1")] 
EnumType2 member2 { get;set; } 
};

Is that possible as well? Is there a way to define an attribute to define the type to convert to something like JsonMemberType("EnumType1")?

Thanks again and regards

Navin

Sent: Thursday, September 18, 2014 1:59 PM

Navin Mishra

unread,
Sep 19, 2014, 1:27:27 PM9/19/14
to jay...@googlegroups.com
Also, meant to ask, it looks like de-serialization that way works with public classes with public members. Could it work (if at all) with internal classes with internal/protected members as well?

Thanks!


From: Navin Mishra <navin...@yahoo.com>
To: "jay...@googlegroups.com" <jay...@googlegroups.com>
Sent: Thursday, September 18, 2014 11:12 AM

Atif Aziz

unread,
Sep 20, 2014, 4:43:09 AM9/20/14
to jay...@googlegroups.com
The sample code I posted earlier, the following line makes the custom ImportContext globally available whenever importing from JSON (e.g., using JsonConvert.Import):

JsonConvert.CurrentImportContextFactory = () => new ImportContext();

This ImportContext's FindImporter method returns a custom EnumImporter (one which allowing importing enumerations from JSON numbers) whenever the destination type is an enumeration. As a result, it should work for all enumerations at any level of depth of objects. In fact you will notice in same sample that I import an array of the Environment.SpecialFolder enumeration:

var folders = JsonConvert.Import<Environment.SpecialFolder[]>("[Desktop,2,Recent,20]");

That's already one level of nesting.

Perhaps if you're case of Thing is not working, it might because the properties are not public and member1 and member2 are mapped to the same JSON member name? I've updated the sample with your Thing class fixed and it seems to be working just fine.

- Atif

Atif Aziz

unread,
Sep 20, 2014, 4:46:58 AM9/20/14
to jay...@googlegroups.com
By default, only public classes and read-write properties are supported with some exceptions. There are plenty of hooks in Jayrock to make things behave the way you like but not without some work. In short, you have to supply your own custom importer implementation as we did with enumerations. What's your exact goal?

- Atif

Navin

unread,
Sep 20, 2014, 8:59:52 AM9/20/14
to jay...@googlegroups.com
Thank you very much for prompt responses! 
Any chance to have a . Net 2.0 version of the sample as
well?

Thanks again and regards 


Navin

unread,
Sep 20, 2014, 9:03:33 AM9/20/14
to jay...@googlegroups.com
 Thanks. The goal is to import json into classes internal to a class library.
The consumers of the library don't need to see these classes, Does that clarify?


Atif Aziz

unread,
Sep 21, 2014, 5:28:25 AM9/21/14
to jay...@googlegroups.com
Jayrock & the sample work on .NET 2.0 just fine.

- Atif

Atif Aziz

unread,
Sep 21, 2014, 5:34:44 AM9/21/14
to jay...@googlegroups.com
The importer responsible for generically importing JSON object as .NET types is ComponentImporter. Jayrock automatically uses it for public classes. For internal classes, you can do the same but have to register specifically, like this:

JsonConvert.CurrentImportContextFactory = () =>

{

    var context = new ImportContext();

    context.Register(new ComponentImporter(typeof(Thing)));

    return context;

};


If you mark the Thing class as internal in the sample then you'll notice that it will still import fine.

- Atif

Navin

unread,
Sep 21, 2014, 9:15:48 AM9/21/14
to jay...@googlegroups.com
Thank you. Doesn't seem to compile when using .net 2 probably because lambda expressions are used...


Atif Aziz

unread,
Sep 21, 2014, 9:19:53 AM9/21/14
to jay...@googlegroups.com
What version of Visual Studio are you using? The C# version can be more recent than your target framework. I tried with Visual Studio 2013, targeting .NET 2.0 but using latest C#.

- Atif

Navin Mishra

unread,
Sep 21, 2014, 11:05:14 AM9/21/14
to jay...@googlegroups.com
Thank you. In a particular project, for some unique reasons, I need to use Visual Studio 2005 with .NET 2.0 :(. In there, the below statement doesn't
compile:


JsonConvert.CurrentImportContextFactory = () => new ImportContext
();

Thanks again and regards


Sent: Sunday, September 21, 2014 6:19 AM

Atif Aziz

unread,
Sep 21, 2014, 3:14:40 PM9/21/14
to jay...@googlegroups.com
Rewrite the lambda as an anonymous method then:

JsonConvert.CurrentImportContextFactory = delegate() { return new ImportContext(); }

- Atif

P.S. This is getting out of the scope of Jayrock. I think you'll find plenty of material online on C# features & how they evolved & using which you can back-port the code.

Navin Mishra

unread,
Sep 22, 2014, 9:14:55 AM9/22/14
to jay...@googlegroups.com
Thank you very much. Will try that!

Thanks again and regards


Sent: Sunday, September 21, 2014 2:34 AM

Navin Mishra

unread,
Sep 22, 2014, 9:18:12 AM9/22/14
to jay...@googlegroups.com
Also meant to ask if the public classes with couple of internal read-write members could be used as well so that, though those specific members are used in importing JSON all right, but are still not visible outside the class library? That would meet the goal too.

Thanks!

Navin Mishra

unread,
Sep 22, 2014, 9:20:47 AM9/22/14
to jay...@googlegroups.com
BTW is there a list of such attributes documented somewhere? 

Thanks!


Atif Aziz

unread,
Sep 22, 2014, 2:19:59 PM9/22/14
to jay...@googlegroups.com
The ComponentImporter I mentioned earlier has a constructor overload that allows you to specify which properties or fields will be considered during an import. Below, I allow public and non-public properties of the Thing class (you need additional logic to just test for internal).

JsonConvert.CurrentImportContextFactory = delegate()

{

    var context = new ImportContext();

    var thingType = typeof(Thing);

    context.Register(new ComponentImporter(thingType,

                        new CustomTypeDescriptor(thingType,

                            thingType.GetProperties(BindingFlags.Instance

                                                    | BindingFlags.Public

                                                    | BindingFlags.NonPublic))));

    return context;

};


The update example can be found at:

- Atif

Atif Aziz

unread,
Sep 22, 2014, 3:20:55 PM9/22/14
to jay...@googlegroups.com
I'm afraid documentation is lacking (except in source code comments, unit tests & samples) but a there's only a handful of attributes:
You can also define your own attributes, which should implement IPropertyCustomzation to participate in customisation for importing & exporting.

- Atif
Reply all
Reply to author
Forward
0 new messages