1

I have a filter object in C#, that contains a dictionary of strings (that represent the propery name) and the corresponding value (expecting an object).

When sending an object of a custom type with JSON to WCF, I use __type in my JSON to deserialize correctly from the JSON object to a C# object. However, when sending a enum (represented as integer in JSON) this will be serialized as integer in C#, because the deserializer has no way of telling what kind of enum it is expecting.

The JSON I send:

{
    "filterList": [
        { "FilterProperty": "Status", "FilterValue": 4 }
        { "FilterProperty": "Status", "FilterValue": 6 }
    ]
}    

The DataContract it deserializes to a list of these:

public class Filter
{
        [DataMember]
        public string FilterProperty { get; set; }
        [DataMember]
        public object FilterValue { get; set; }
}

The FilterValue corresponds in this specific situation with the an enum. But because the FilterValue property is defined as object, the deserializer does not know how to deserialize it without additional information.

Is it possible to send additional information with JSON to let WCF correctly deserialize the enum even if an object is expected?

Or is the only way to solve this to use reflection to resolve the type from the filter property name?

Ricconnect
  • 1,089
  • 5
  • 25
  • Do you use DataContracts in your WCF service? If you use only dictionaries it is obvious that serializer will don't find correct enum type. – rraszewski Jan 21 '15 at 08:18
  • http://stackoverflow.com/questions/2441290/json-serialization-of-enum-as-string – Amit Jan 21 '15 at 08:18
  • @rraszewski I use DataContracts, and it is not a native dictionary. What do you mean exactly with 'if you use only dictionaries it is obvious that serializer will don't find correct enum type'? – Ricconnect Jan 21 '15 at 08:23
  • @Amit I do not want to send my enum over the line as strings, that it not the problem. The problem is that I send a enum as integer to my WCF server, and I want it to deserialize it correctly. However, the server cannot do this implicitly because it expects an object instead of a specific Enum type. – Ricconnect Jan 21 '15 at 08:25
  • Please annotate your question with code sample demonstrating your problem. Sentences such as *Is it possible to send additional information with JSON to let WCF correctly deserialize the enum even if an object is expected* do not really make much sense on their own. – tom redfern Jan 21 '15 at 08:41
  • @Tom Redfern you are right, I updated the question and I hope it is more clear now. – Ricconnect Jan 21 '15 at 08:53
  • Is there any reason you're using `object` rather than an actual enum type in your Filter class? – tom redfern Jan 21 '15 at 08:58
  • @Tom Redfern The filter class is usable for any property, not only for that specific enum type. – Ricconnect Jan 21 '15 at 08:59
  • In that case see my answer below. – tom redfern Jan 21 '15 at 09:05
  • Are you attached to `DataContractJsonSerializer` or are you willing to switch to [Json.NET](http://james.newtonking.com/json), which has different ways to handle polymorphic fields? – dbc Jan 21 '15 at 11:01
  • Also, with `DataContractJsonSerializer`, you must pre-specify all [known types](https://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializer.knowntypes%28v=vs.110%29.aspx). If `FilterValue` can be any type in your domain, then are you setting known types to include all types in your domain? – dbc Jan 21 '15 at 11:08
  • @dbc To handle polymorphic fields, I send a "__type" field with every object I send to the serer. This results in a correct deserialization. Only Enums are not deserialized correctly. I don't think any deserializer can determine the enum type that the received integer needs. – Ricconnect Jan 21 '15 at 11:22

1 Answers1

0

No, there is no extra information you can embed in the JSON to instruct deserializers to set the type of a property of type object to anything other than object.

If you need to be able to support multiple types polymorphically across the WCF service boundary you can define an interface to represent your type, in this case something like IFilterValue, and then use the ServiceKnownType attribute to tell WCF about the supported implementations of the interface.

Hope this is of help.

EDIT

It seems to me another more interoperable solution would be to do something like:

public class Filter
{
    [DataMember]
    public string FilterProperty { get; set; }

    [DataMember]
    public string Type { get; set; }

    [DataMember]
    public string FilterValue { get; set; }
}

This means that rather than unboxing an object you can do an explicit string conversion which strikes me as a better option.

tom redfern
  • 30,562
  • 14
  • 91
  • 126
  • The `FilterPropery` can contain a reference to a property of literally every model of our domain. It is not possible to define a ServiceKnownType for every type that is used by the filter. – Ricconnect Jan 21 '15 at 09:17
  • In that case you have few choices other than to refactor your service contract to remove the property, or to unbox the property value at some later point in your code, based on what the FilterProperty is set to. – tom redfern Jan 21 '15 at 09:30
  • I don't think there is any other way then to use `object` when you want to expose a filter object that is usable for every class :) But the option to use reflection to unbox the property seems the only option then. – Ricconnect Jan 21 '15 at 09:34
  • Besides a JSON endpoint, the service has a SOAP endpoint, which deserializes correctly. If I would change the FilterValue in a String, the deserialization which the SOAP endpoint would not work anymore. – Ricconnect Jan 21 '15 at 11:20
  • Thank you very much for the effort! – Ricconnect Jan 21 '15 at 13:39