C# JavascriptSerializer failing with EF object: RecursionLimit exceeded - c#

I wanted a cheap way to clone a database object. My plan was to serialize and then deserialize the object. My code is as follows:
var newHireRequisition =_context.NewHireRequisitions.Single(x => x.newHireRequisitionPk == newHireRequisitionId);
JavaScriptSerializer js = new JavaScriptSerializer();
js.RecursionLimit = 1;
var json = js.Serialize(newHireRequisition);
NewHireRequisition newReq = js.Deserialize<NewHireRequisition>(json);
As you can see, I set recursion level to one to keep from traversing the relationships of the NewHireRequisitions table. I believe that this is a bug in the 'Serialize' function.
When this code runs, I get an exception on the Serialize command. The exception is:
System.ArgumentException: 'RecursionLimit exceeded.'
The datamodel looks like this:
but I only want the one object in the middle (NewHireRequisition), not the related rows.
Any help with this technique would be appreciated, or another way to shallow clone an entity framwork data object.

Thanks to #crashmaster! Looking at the newtonsoft web page, I see that the Json.Net serializer supports LINQ to JSON, while the .net native JavaScriptSerializer does not. That resolved my issue.

Related

Is it possible to deserialize json string into dynamic object using System.Text.Json?

I am using System.Text.Json package to use the serialization and deserialization.
I can deserialize a json string into an object when the type is explicitly specified like below.
var data = JsonSerializer.Deserialize<PersonType>(jsonString);
But the dynamic type does not work. Is it possible to deserialize without having to specify the type? Thank you!
var data = JsonSerializer.Deserialize<dynamic>(jsonString);
tl:dr JsonNode is the recommended way but dynamic typing with deserializing to ExpandoObject works and I am not sure why.
It is not possible to deserialize to dynamic in the way you want to. JsonSerializer.Deserialize<T>() casts the result of parsing to T. Casting something to dynamic is similar to casting to object
Type dynamic behaves like type object in most circumstances. In particular, any non-null expression can be converted to the dynamic type. The dynamic type differs from object in that operations that contain expressions of type dynamic are not resolved or type checked by the compiler. The compiler packages together information about the operation, and that information is later used to evaluate the operation at run time
docs.
The following code snippet shows this happening with your example.
var jsonString = "{\"foo\": \"bar\"}";
dynamic data = JsonSerializer.Deserialize<dynamic>(jsonString);
Console.WriteLine(data.GetType());
Outputs: System.Text.Json.JsonElement
The recommended approach is to use the new JsonNode which has easy methods for getting values. It works like this:
JsonNode data2 = JsonSerializer.Deserialize<JsonNode>(jsonString);
Console.WriteLine(data2["foo"].GetValue<string>());
And finally trying out this worked for me and gives you want you want but I am struggling to find documentation on why it works because according to this issue it should not be supported but this works for me. My System.Text.Json package is version 4.7.2
dynamic data = JsonSerializer.Deserialize<ExpandoObject>(jsonString);
Console.WriteLine(data.GetType());
Console.WriteLine(data.foo);
I have tried using System.Text.Json in a dynamic way and it just does not work in an easy and meaningful way it seems. So while not a direct answer to your question, but I was "forced" to use the good old Newtonsoft.Json that just works:
dynamic result = JObject.Parse(message);

Generate JSON string from dynamic ExpandoObject

I am using C# and trying to generate a JSON string from a dynamic object.
dynamic reply = new System.Dynamic.ExpandoObject();
reply.name = "John";
reply.wins = 42;
string json = System.Web.Helpers.Json.Encode(reply);
System.Console.WriteLine(json);
(Note, the above requires a reference to the System.Web.Helpers assembly.)
I was hoping for this to output the string:
{"name":"John","wins":42}
But it actually outputs:
[{"Key":"name","Value":"John"},{"Key":"wins","Value":42}]
What do I need to change to get the output I was hoping for?
Just download the Newtonsoft.Json Nuget package.
That's the preferred way of working with json in c#.
Your code using Newtonsoft would be:
dynamic reply = new System.Dynamic.ExpandoObject();
reply.name = "John";
reply.wins = 42;
string json = Newtonsoft.Json.JsonConvert.SerializeObject(reply);
System.Console.WriteLine(json);
EDIT:
I just want to explain better why you're getting that result when you're using the System.Web.Helpers.Json.Encode method.
An ExpandoObject is an object which fields are defined at runtime, different than a regular object which fields/properties/methods .. are defined at compile-time. To be able to define them at run-time the expando object internally holds a dictionary, which is a collection of key-value pairs.
I don't know how that helper works but it's probably just a simple serializer and that's why it's serializing to an array of key- value pairs instead of the actual object you're expecting. The library Newtonsoft.Json is almost an standard for c# projects and obviously is aware of how the Expando Object works internally.
Using the Newtonsoft.Json tools:
using Newtonsoft.Json;
/// skip a bunch of other implementation details.
var json = Newtonsoft.Json.JsonConvert.SerializeObject(reply);
That's how I do it.

Cast exception during serialisation of a tree structure to JSON

I have been working on a little project and have stumbled into an issue. I have been using the object type implemented here during the project and wished to be able to convert it to a JSON string through the Newtonsoft Json.NET library and then save it to a text file. I have previously tested the class with custom structures and the like and found no issues with it so far, however when I attempted to serialise the object the exception below was shown:
Unable to cast object of type 'AuriEngineTest.Node`1[System.String]' to type 'System.String'.'
A minimal example of the code leading up to this point can be found below:
Node<string> scene;
scene = new Node<string>("Root");
var textToSave = JsonConvert.SerializeObject(scene);
string fileLocation = "C://..."
File.WriteAllText(fileLocation, textToSave);
I wish to clarify if the custom class used to create the Node structure is for some reason not supported, and if that is the case is there an alternative method to serialise the object, be it to JSON or a viable alternative.
Kind regards,
Shadow

Serialize an array into JSON objects using .NET

The serialization of the array returns the following JSON:
[{"Code":"AAAA","Description":"Description of AAAA"},{"Code":"BBBB","Description":"Description of BBBB"}]
My goal is to return the following JSON:
{"AAAA":{"Description":"Description of AAAA"},"BBBB":{"Description":"Description of BBBB"}}
You can achieve something simliar (not exactly the same you are expecting) if instead of serializing an array, build a temporary Dictionary and serialize it.
var dict = new Dictionary<String, YourClass>();
foreach (YourClass yourObj in listOfObjs)
{
dict[yourObj.Code] = yourObj;
}
// then serialize "dict"
You could add a rule to your JSON serializer to make it avoid serializing "code" property in YourClass, and you will end up with a JSON object exactly as you show in your example.
You'll need to either use a class that has the "AAAA" and "BBBB" properties, or you'll need to serialize a dictionary instead. As it is, you're serializing an array and getting an array.
The table on this blog post shows several search starting points.
.Net has built-in System.Web.Script.Serialization.JavaScriptSerializer, here, with examples
The .Net one doesn't specially serialize Dictionary the way you want, but some of the others do, I believe. However, I think there are reasons NOT to want a general serialization routine the way you've requested - though I can't list them certainly.

How to dynamically create a JSON object in c# (from an ASP.NET resource file)?

I need to serialize the strings from a resource file (.resx) into a JSON object. The resource file's keys are in flux and thus I cannot just create a C# object that accepts the appropriate values. It needs to be a dynamic solution. I am able to loop through the key-value pairs for the file, but I need an easy way to serialize them to JSON.
I know I could do:
Object thing = new {stringOne = StringResource.stringOne; ...}
But, I'd rather have something like:
Object generic = {}
foreach (DictionaryEntry entry in StringResource) {
generic.(entry.Key) = entry.Value
}
Or should I just create a custom JSON serializer that constructs the object piecemeal (i.e. foreach loop that appends part of the JSON string with each cycle)?
EDIT
I ended up writing a quick JSON serializer that constructs the string one field at a time. I didn't want to include a whole JSON library as this is the only use of JSON objects (for now at least). Ultimately, what I wanted is probably impractical and doesn't exist as it's function is better served by other data structures. Thanks for all the answers though!
If you're using C# 4.0, you should look at the magical System.Dynamic.ExpandoObject. It's an object that allows you to dynamically add and remove properties at runtime, using the new DLR in .NET 4.0. Here is a good example use for the ExpandoObject.
Once you have your fully populated ExpandoObject, you can probably easily serialize that with any of the JSON libraries mentioned by the other excellent answers.
This sounds like an accident waiting to happen (i.e. creating output prior to cementing the structure), but it happens.
The custom JSON serializer is a compelling option, as it allows you to easily move from your dictionary into a JSON format. I would look at open source libraries (JSON.NET, etc) to see if you can reduce the development time.
I also think setting up in a slightly more structured format, like XML, is a decent choice. It is quite easy to serialize from XML to JSON using existing libraries, so you avoid heavy customization/
The bigger question is what purposes will the data ultimately serve. If you solve this problem using either of these methods, are you creating bigger problems in the future.
Probably I would use JSON.NET and the ability to create JSON from XML.
Then, you could create an XML in-memory and let JSON.NET convert it to JSON for you. Maybe if you dig deeper into the API, there are other options, too.
Newtonsoft is a library that has all kinds of nifty JSON tools...among them, on-the-fly one-line serializer and deserializers...check it out, it's my favorite JSON library out there
http://james.newtonking.com/pages/json-net.aspx
If I remember correctly, it has a class that will convert JSON to a .NET object without having to create the .NET object first. Think it is in the Json.Convert class
The way I do it is:
var serialiser = new System.Web.Script.Serialization.JavaScriptSerializer();
string json = serialiser.Serialize(data);
context.Response.Write(json);

Categories