(De)serializing Json with System.Text.Json and Newtonsoft.Json - c#

I'm working on a legacy system that works with IotHub SDK. The application uses both System.Text.Json (there's an agreement to use this for current & future development) and Newtonsoft.Json for (de)serializing JSON.
I need to deserialize the following JSON into a Dictionary<string,object> because the value can either be a string or a JSON object:
{
"route1": "route 1 text",
"route2": {
"route": "route 2 text",
"priority": 1,
"timeToLiveSecs": 60
}
}
What I expect is that the value would be deserialized as:
route1 as string
route2 as object
But System.Text.Json deserializes both values as JsonElement. And to get the value, a method like GetString() needs to be called (see last row)
Because of the usage combination of Newtonsoft & System.Text.Json in this legacy application, serializing this object with Newtonsoft doesn't work.
The deserialization & re-serialization only works when the same libraries were used in both process. And IoTHub SDK from Microsoft itself, uses Newtonsoft.Json.
Is there a way to make both libraries work together in this case?
I find it dangerous to use either one to deserialize an object type with this behavior, when there's a chance 3rd party libraries may use another library.

As taken from the official docs: "System.Text.Json is strict by default and avoids any guessing or interpretation on the caller's behalf, emphasizing deterministic behavior. The library is intentionally designed this way for performance and security. Newtonsoft.Json is flexible by default. This fundamental difference in design is behind many of the following specific differences in default behavior."
Source: https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/migrate-from-newtonsoft?pivots=dotnet-7-0
The core principle between Newtonsoft and the Microsoft differs as you can see. Also stated in the docs: "JsonElement is what you can search and enumerate over, and you can use JsonElement to materialize JSON elements into .NET types."
As seen in your screenshot, System.Text.Json detects the right type (string) -> see the ValueKind property. You can access the property and do your handling. Other than that, no there is no way to use both libs interchangeably since they have a different approach.
withJsonDeserializer["route1"].ValueKind

Related

C# Invalid Option Error deserializing nested dynamic object with system.text.json in .Net 6

I'm working with a lot of media files and turning their properties into a dynamic object to process them in VS 2022, C#, .Net 6 Core, and system.text.json. Most of the files have nested parameters. Since every audio/video file has a different type and number of parameters, POCO's don't make sense here and these dynamic objects have been extensively used throughout this and other parts of the system... making them impossible to replace.
After processing the media files and adding additional information to the objects, I want to serialize them with system.text.json into a string. When I do, I'm getting an error that says:
public static string ObjectToString(dynamic o)
{
return System.Text.Json.JsonSerializer.Deserialize<dynamic>(o);
// stupid typo... should be serialize here
}
System.Text.Json.JsonSerializer.Deserialize<object>(System.Text.Json.JsonDocument,
System.Text.Json.JsonSerializerOptions)' has some invalid arguments'
Actually, I've tried serializing the same object I just serialized without modification and get the same error.
In .Net Framework, Newtonsoft had no trouble doing this, but in Core, I'd like to get away from it if possible. So, what do I need to do in order to deserialize dynamic objects to strings?
Wait, you want to go from an object to a string? That's serialization, no deserialization.
Also, if you read your error, the method you're calling requires two arguments, the object you're serializing (?) and a JsonSerializerOptions instance that defines how the serialization should happen.

Use protobuf-net to convert json into object

I have been provided a c# class generated through protogen.
I have a json response which I want to convert into object(map to the class generated from protogen).
How can I achieve this ?
The Json that I have is like:
Test {Id:"0000001" InsertDateTime:"4/12/2018 01:01:01" ModifyDateTime:"4/12/2018 01:05:10" ParentId:"0000001"
Sample{Id:"0000002" InsertDateTime:"4/12/2018 01:01:01" ModifyDateTime:"4/12/2018 01:05:10"}
}
The main class name is 'Test' and it has int, string properties as well as properties of type 'class' as well.
I want to convert this Json to 'protogen' generated class object.
protobuf-net only implements the binary Protocol Buffers (ProtoBuf) specification.
It is unclear whether by "json" you mean "general purpose JSON, nothing to do with ProtoBuf", or whether you mean "the Protocol Buffers JSON format added around 3.0".
If you mean general purpose JSON: then usually just about any JSON serializer will work fine - Json.NET is a good default, but other JSON serializers exist. This is because protobuf-net tries to work with idiomatic .NET objects, which means that it tends to play very nicely with other tools that work with idiomatic .NET objects.
If you mean the ProtoBuf-specific JSON, then I would suggest using Google's official C# ProtoBuf library, which implements this. I simply haven't had need or time to add support for this into protobuf-net, and to date adding it has been a very low priority for me - I simply haven't seen anyone asking for it from me.
If you have generic JSON, but the JSON layout is different to your protobuf model, then frankly I would recommend having two DTO models:
one that is designed to work with your JSON data and your chosen JSON serializer (such as Json.NET)
one that is designed to work with your ProtoBuf data and your chosen ProtoBuf serializer (such as protobuf-net)
and simply map between the two representations with regular C# code (or any auto-mapper tool of your choosing).
You can sometimes fight a serializer library to get it work with an object model that doesn't match the shape of the data, but in my experience this is a bad use of time and leads to brittle, buggy code.

JSON Serialization Output Contains Count Property

I'm trying to serialize an array of objects into JSON in C#. By array I mean something like Object[] (not Array<Object>), I'm using a JsonMediaTypeFormatter as part of MVC (the serialization is happening automatically as part of the framework but I can override it). The output contains {"count":2,"value":[{...},{...},...]}" where the ... is the json representation of the object. I've looked around and haven't found much information about suppressing this behavior. I want the output to just be the [{...},{...},...] rather than the object with count and values properties. Does anyone know how to achieve this without manually writing the code to do the serialization?
You could consider an alternative framework like the JSON.NET framework. I don't know how much you can customize if you are using an in-built .NET object since there are public properties that are not being ignored. Not using the JSONMediaTypeFormatter much, if it allows you to ignore properties, consider overriding List or ArrayList to hide certain attributes.
I would recommend not returning an array directly as there is a security flaw that could be compromised in a client browser (if that is the consumer). See this reference to find out more.

DataContractSerializer, Ordering inconsistency between .Net and Mono

For DataContractSerializer, items in XML must be ordered.
It is by "Order" attribute. Or in alphabetical order for .NET
For a Mono, it is ignored, so order is as data members mentioned in the serializable class. The bug with Mono is described here:
https://bugzilla.xamarin.com/show_bug.cgi?id=10545
Now, the problem is, we have a big project working on Mono. There are tons of config (XML-Config) files. As well as tons of Serializable objects.
In order for this to work in .Net, while still to be compatible with both, Mono and .Net, I have following options:
Explicitly add "Order" attribute to each of the serializable objects. So, .Net will repeat the same same numbering
Switch to the XmlSerializer. For this one I have to change attributes which are different between both. E.g., XML one includes all attributes unless it is told opposite (ignore attribute)
Both #1 and #2 assume lot of work. Is there a way or Serializer implementation, which will reuse existing Data classes done for DataContractSerializer?

What's the difference between DataContractJsonSerializer and JavaScriptSerializer?

The .NET Framework ships with System.Runtime.Serialization.Json.DataContractJsonSerializer and System.Web.Script.Serialization.JavaScriptSerializer, both of which de/serialize JSON. How do I know when to choose one of these types over the other? MSDN doesn't make it clear what their relative advantages are.
We have several projects that consume or emit JSON, and the class selected for each thus far has depended on the opinion of the primary dev on each project. Some are simple, two have complex logic regarding producing managed types from JSON (the types do not map closely to the streams) but don't have any emphasis on speed, one requires speed. None interact with WCF, at least as of now.
While I'm interested in alternative libraries, I am hoping that somebody might have an answer to my question too.
The DataContractJsonSerializer is intended for use with WCF client applications where the serialized types are typically POCO classes with the DataContract attribute applied to them. No DataContract, no serialization. The mapping mechanism of WCF makes the sending and receiving very simple, but only if your platform is homogeneous. If you start mixing in different toolsets, your program might go sideways.
The JavaScriptSerializer can serialize any type, including anonymous types (one way), and does so in a more conformant way. You lose the "automagic" of WCF, but you gain more integration options.
As you can see by the comments, there are a lot of options out there for AJAX serialization, and to address your speed vs. maintainability questions, it might be worth investigating them to find a solution that meets the needs of all the teams, to reduce maintainability issues in the long term as everybody does things their own way.
2014-04-07 UPDATE:
I suggest using JSON.NET if you can. See http://james.newtonking.com/json Feature Comparison for a review of the 3 libraries considered in this question.
2015-05-26 UPDATE:
If your company requires the use of commercially licensable products, or you need every last bit of performance, you may also want to check out https://servicestack.net/.
Both do approximately the same but using very different infrastructure thus applying different restrictions on the classes you want to serialize/deserialize and providing different degree of flexibility in tuning the serialization/deserialization process.
For DataContractJsonSerializer you must mark all classes you want to serialize using DataContract atrtibute and all members using DataMember attribute. As well as if some of you classes have enum members, then the enums also must be marked as DataContract and each enum member - with EnumMember attribute.
Also DataContractJsonSerializer allows you fine control over the whole process of serialization/deserialization by altering types resolution logic and replacing the types you serialize with surrogates.
For JavaScriptSerializer you must provide parameterless constructor if you plan on deserializing objects from json string.
For me, I usually use JavaScriptSerializer in presentation logic, where there's a simple model I want to render in Json together with page, without additional ajax requests. And I even usually don't have to deserialize them back to c# - so there's no overhead at all. But if it's persistence logic, where I want to save objects into a data store (usually no-sql storage), to load them later, I prefer using DataContractJsonSerializer because the overhead of putting attributes is worth of flexibility in the serialization/deserialization process tuning, especially when it comes to loading of serialized data into the objects of the newer version, with updated definitions
Personally, I think that DataContractJsonSerializer reeks of over-engineering. I'd skip it and go with JavaScriptSerializer. In the event where JavaScriptSerializer isn't available, you can use FridayThe13th (a library I wrote ;p).

Categories