-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[System.Text.Json] serialize/deserialize any object #30969
Comments
I would always recommend specifying the type you're expecting no matter what. Alternatively, wrap your serialized objects in an envelope that contains the type manually. |
I don't know the type at compile time. |
Having the JSON payload define the type being created during deserialization isn't something we'd want to support in S.T.Json and certainly not by default. The object you get back with S.T.Json will be a box'd JsonElement which encapsulates the raw JSON token itself, and you would have to process that to turn into the concrete type that you need.
Maybe you could try augmenting your object model to have a "type" property, and then use that (after deserialization) to figure out at runtime which type to new up from the |
The decision to leave out For further reading, see https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf and https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf. |
I do understand the security concerns. Maybe the user could configure a list of allowed assemblies where the type can come from. I will certainly do this in my code. I added
It works, but here I need to convert the object to a string to a
This is not in a hot path in my app, but I'd still prefer not to do that indirection (without doing too much refection myself). Similarly in |
I reiterate:
Almost any possible implementation of ParseTypeName I can think of will have a security vulnerability of some type. If you really need some type of polymorphic behavior, one potentially safe way to do this would be to have One possible way to work around the situation you're experiencing now where you need to disassembly and reconstruct the payload is to keep the type information separate from the object data. For example, instead of: {
"$type": 1,
"field1": "value1",
"field2": "etc."
} Try: {
"$type": 1,
"data": {
"field1": "value1",
"field2": "etc."
}
} If you maintain the invariant that the |
Ok, thanks! We'll have to think about the type more. I managed to use a But how can I optimize serialization? Can I get the So that I can avoid the diversion over string and JsonDocument as in this code:
|
Yes. There's a static method on |
Thanks, I didn't see that overload. That makes the workaround much better. That workaround suffices for my current needs. I still think, that the type will have to be added for some circumstances like (de)serializing interfaces and base types (and lists of these). But this is most probably something for .NET 5. I don't need this issue anymore, but I don't know if you want to keep it for .NET5. If not, feel free to close it. |
There are legitimate use case for adding the $type property, the breeze js library depends on it for example. Unsafe de-serialization is an separate matter. you can object to supporting that and still let us add the $type property easily. |
I understand the security risk for exposed JSON, but for internal handling where the JSON is not exposed to the public, a I, too, serialize types containing |
I have the same issue. I am writing an apis to collect data from Microsoft Azure DevOps. Their serialized json contains $type. So I am at a loss as how to deserialize these fields. |
Wanted to comment on another use case...it looks like this prevents System.Text.Json from being used with xunit. Without the ability to deserialize into the actual objects and not wrapped JsonElements, I can't output If this works in the way I think it works, this is an automatic blocker from adoption System.Text.Json. |
The argument to not support polymorphic deserialization because it opens vulnerabilities and then suggesting to use an envelop as a wrapper that does exactly that makes no sense. It opens the same vulnerabilities and halves the performance because now you have to (de)serialize the data twice. In this scenario newtonsoft outperforms stjson easily. (My usecase doesn't involve websites anyway so why?) But maybe c#9 can help to support polymorphic deserialization for data classes (if data classes support inheritance at all). Also if you would allow this only given a base type that is known to be secure there wouldn't be any issues. |
I also serialize types containing interfaces. The serializer must know what the concrete type was when deserializing. I don't want to set up type mapping etc. |
@jeremy-morren Please see #29937 |
My workaround currently: JsonSerializer.Serialize((object)data) For enumerable objects: // ToList() is needed!
JsonSerializer.Serialize(data.Cast<object>().ToList()) |
I have figured out the same approach works for me, is there any drawbacks to this though I am wondering? |
I try to convert my Newtonsoft.Json code to System.Text.Json and I came along a problem.
I need to serialize/deserialize any object. I don't know the objects type at compile time.
With Newtonsoft.Json I did this:
The serialized json contained a "$type" with the full name of the type (namespace, classname, assemblyname).
With this info the deserializer knew what object to instantiate.
Is this also possible with System.Text.Json? How?
The text was updated successfully, but these errors were encountered: