2

I there, I'm working on a c# application

I Have a situation where i get an object from a web service, say

MyObject{
   public bool MyProp
}

And I can't modify that object, but i need to serialize MyObject to a json string but MyProp has to be converted to 1 or 0 instead of true/false.

I'm using JavaScriptSerializer to serialize to Json

Any idea?

tks

dbc
  • 104,963
  • 20
  • 228
  • 340
DJPB
  • 5,429
  • 8
  • 30
  • 44
  • Can you share with us the error you get when you are trying to de-serialize the object? JSON should understand the boolean property with out issue. Worst case, send it via a string property and do your conversions client side. – Kevin B Burns Jul 18 '16 at 17:36
  • 1
    Are you willing to switch to Json.NET? If so, see [Convert an int to bool with Json.Net](https://stackoverflow.com/questions/14427596/convert-an-int-to-bool-with-json-net/14428145#14428145). – dbc Jul 18 '16 at 17:40

1 Answers1

3

If you are willing to switch to , you can use the solution from Convert an int to bool with Json.Net.

If you wish to continue using JavaScriptSerializer, you will need to create a JavaScriptConverter for your MyObject type as follows:

class MyObjectConverter : JavaScriptConverter
{
    public override IEnumerable<Type> SupportedTypes
    {
        get { return new[] { typeof(MyObject) }; }
    }

    // Custom conversion code below

    const string myPropName = "MyProp";

    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        object value;
        if (dictionary.TryGetValue(myPropName, out value))
        {
            dictionary[myPropName] = !value.IsNullOrDefault();
        }

        var myObj = new JavaScriptSerializer().ConvertToType<MyObject>(dictionary);
        return myObj;
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        var myObj = (MyObject)obj;

        // Generate a default serialization.  Is there an easier way to do this?
        var defaultSerializer = new JavaScriptSerializer();
        var dict = defaultSerializer.Deserialize<Dictionary<string, object>>(defaultSerializer.Serialize(obj));

        dict[myPropName] = myObj.MyProp ? 1 : 0;

        return dict;
    }
}

public static class ObjectExtensions
{
    public static bool IsNullOrDefault(this object value)
    {
        // Adapted from https://stackoverflow.com/questions/6553183/check-to-see-if-a-given-object-reference-or-value-type-is-equal-to-its-default
        if (value == null)
            return true;
        Type type = value.GetType();
        if (!type.IsValueType)
            return false; // can't be, as would be null
        if (Nullable.GetUnderlyingType(type) != null)
            return false; // ditto, Nullable<T>
        object defaultValue = Activator.CreateInstance(type); // must exist for structs
        return value.Equals(defaultValue);
    }
}

Then use it like:

        var serializer = new JavaScriptSerializer();
        serializer.RegisterConverters(new JavaScriptConverter[] { new MyObjectConverter() } );

        var json = serializer.Serialize(myObject);

Note - even though your MyObject class only has one property, I wrote the converter under the assumption that in real life it could have additional properties that should be serialized and deserialized automatically, for instance:

public class MyObject
{
    public bool MyProp { get; set; }

    public string SomeOtherProperty { get; set; }
}
dbc
  • 104,963
  • 20
  • 228
  • 340