-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
Orleans unable to deep copy JObject #299
Comments
Can you please share the value of this JObject, the string it was created from. |
The value doesn't really matter; the error is happening at compile time. Just create a method in a grain that returns |
We looked into this issue and it's a bit subtle. JObject is not serializable. The bigger question is whether you really need to pass the non-serializable JObject in remote calls. Why don't you turn it into string (JObject.ToString) and on the recipient side parse it back (JObject.Parse). Would that solve your problem? |
Thanks for the detailed explanation! |
I see more than one option here. If JObject was .NET serializable, everything would presumably just work. I think this would be best because it would encapsulate the conversion logic within the Newtonsoft library and would evolve in the future as necessary. Not sure how likely this is, considering that we are talking about making types of a serialization library themselves serializable in a different context. We could add special serializers for JObject and related types. A little bit of work. The concern is it could break with any breaking change or extension of the Newtonsoft code. Another potential option is to treat JObject and related types as special cases and convert them to/from strings on the fly like we convert this references passed by grain code as arguments in codegen. This would only work for simple case, not for arrays, dictionaries, etc. So I don't think this is a good option.
Can you point to an example? |
I've run into this problem multiple times, too. Eg, when I first started trying to implement Event Sourcing, properties of type Could we add an attribute to tell Orleans' to codegen serializers for types in other assemblies? Something akin to KnownType. We could fix this for JObject/JValue by being able to externally attach a serializer to those types, then we could just serialize/deserialize using JSON.NET instead of the generated serializer. |
@ReubenBond , we have been thinking about this issue recently, so let me please share some of our thoughts. Question (b) is an important and valid question, but this issue is NOT about it. We can open a separate issue about (b). For me, it would be somewhat similar to issue #37 - how to use Bond in Orleans. We are discussing question (a) here:
The question is: should we?
Perhaps there are scenarios where serializing JObject is required? |
My apologies, I wasn't clear. I'm suggesting we implement (2), the extension point for attaching serializers to arbitrary types. JObject is not [Serializable], but it can be serialized quite easily. Edit: I'd serialize JObject & XmlElement to their native types, JSON & XML respectively, which I believe is the intention behind them not being [Serializable]. |
When you return a JObject from an ApiController, it just works. In fact, tools such as Postman are able to recognize JSON and nicely format the output of a request returning a JObject. I guess this means that they are doing the conversion to/from string automatically. Probably not a very strong use case though.
I personally don't have a very strong use case. It seems like a nice to have but not necessary feature. |
@nehmebilal usually you would return a concrete type from your ApiController, so that should be fine - you can codegen from your grain interfaces (just be wary of possibly security implications). However, if you have a method which accepts a parameter of type |
We already solved the compile time error that @nehmebilal reported above ('Newtonsoft.Json.Linq.JPropertyKeyedCollection' is inaccessible due to its protection level) in #305. We will provide a way to do (2) from above: "provide an extension point for application to define its own Serializer for JObject." |
Great! |
Ok, good news: so apparently we supported (2) all way long! Kudos to @alan-geller for doing that work years ago and @sergeybykov for pointing me to this! |
I think the issue can be closed now? |
Orleans is generating the following code to deep copy JObject; which doesn't compile because JPropertyKeyedCollection is an internal class to JObject.
object temp12 = ((Newtonsoft.Json.Linq.JPropertyKeyedCollection)(Orleans.Serialization.SerializationManager.DeepCopyInner(fieldInfo12.GetValue(input))));
Console output:
error CS0122: 'Newtonsoft.Json.Linq.JPropertyKeyedCollection' is inaccessible due to its protection level
The text was updated successfully, but these errors were encountered: