Can JavaScriptSerializer exclude properties with null/default values?
Asked Answered
F

7

39

I'm using JavaScriptSerializer to serialize some entity objects.

The problem is, many of the public properties contain null or default values. Is there any way to make JavaScriptSerializer exclude properties with null or default values?

I would like the resulting JSON to be less verbose.

Feign answered 7/9, 2009 at 6:0 Comment(0)
F
15

The solution that worked for me:

The serialized class and properties would be decorated as follows:

[DataContract]
public class MyDataClass
{
  [DataMember(Name = "LabelInJson", IsRequired = false)]
  public string MyProperty { get; set; }
}

IsRequired was the key item.

The actual serialization could be done using DataContractJsonSerializer:

public static string Serialize<T>(T obj)
{
  string returnVal = "";
  try
  {
    DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
    using (MemoryStream ms = new MemoryStream())
    {
      serializer.WriteObject(ms, obj);
      returnVal = Encoding.Default.GetString(ms.ToArray());
    }
  }
  catch (Exception /*exception*/)
  {
    returnVal = "";
    //log error
  }
  return returnVal;
}
Feign answered 8/2, 2010 at 21:55 Comment(2)
For the DataContractJsonSerializer you need to set EmitDefaultValue to false on the DataMemberCelebrate
this seems interesing but needs more explanation, specially the first codeSkolnik
M
36

FYI, if you'd like to go with the easier solution, here's what I used to accomplish this using a JavaScriptConverter implementation with the JavaScriptSerializer:

private class NullPropertiesConverter: JavaScriptConverter {
 public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer) {
  throw new NotImplementedException();
 }

 public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer) {
  var jsonExample = new Dictionary<string, object >();
  foreach(var prop in obj.GetType().GetProperties()) {
   //check if decorated with ScriptIgnore attribute
   bool ignoreProp = prop.IsDefined(typeof(ScriptIgnoreAttribute), true);

   var value = prop.GetValue(obj, BindingFlags.Public, null, null, null);
   if (value != null && !ignoreProp)
    jsonExample.Add(prop.Name, value);
  }

  return jsonExample;
 }

 public override IEnumerable<Type> SupportedTypes {
  get {
   return GetType().Assembly.GetTypes();
  }
 }
}

and then to use it:

var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new JavaScriptConverter[] {
  new NullPropertiesConverter()
});
return serializer.Serialize(someObjectToSerialize);
Motorize answered 19/7, 2012 at 21:9 Comment(4)
Should point out that if you want fields as well the code is missing itTillman
If you wondered what the previous comment was talking about: #295604Appetency
You could also make this slightly faster by checking the ignoreProp first and not getting the value unless it is false.Eshelman
Great solution! If you are not getting any results, remember to have {get;set;} on your object properties for reflection to return them in GetProperties(),Jasminjasmina
F
15

The solution that worked for me:

The serialized class and properties would be decorated as follows:

[DataContract]
public class MyDataClass
{
  [DataMember(Name = "LabelInJson", IsRequired = false)]
  public string MyProperty { get; set; }
}

IsRequired was the key item.

The actual serialization could be done using DataContractJsonSerializer:

public static string Serialize<T>(T obj)
{
  string returnVal = "";
  try
  {
    DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
    using (MemoryStream ms = new MemoryStream())
    {
      serializer.WriteObject(ms, obj);
      returnVal = Encoding.Default.GetString(ms.ToArray());
    }
  }
  catch (Exception /*exception*/)
  {
    returnVal = "";
    //log error
  }
  return returnVal;
}
Feign answered 8/2, 2010 at 21:55 Comment(2)
For the DataContractJsonSerializer you need to set EmitDefaultValue to false on the DataMemberCelebrate
this seems interesing but needs more explanation, specially the first codeSkolnik
B
7

For the benefit of those who find this on google, note that nulls can be skipped natively during serialization with Newtonsoft.Json

var json = JsonConvert.SerializeObject(
            objectToSerialize,
            new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore});
Barbaresi answered 31/8, 2017 at 15:10 Comment(0)
V
4

You can implement a JavaScriptConverter and register it using the RegisterConverters method of JavaScriptSerializer.

Veliavelick answered 7/9, 2009 at 6:12 Comment(0)
J
4

Json.NET has options to automatically exclude null or default values.

Jodyjoe answered 7/9, 2009 at 21:55 Comment(2)
OP was asking about JavaScriptSerializer, not json.net.Clavier
@JustinR. looks like he is the author of Json.NET and that's probably whySanguinolent
N
1

This code is block null and default(0) values for numeric types

private class NullPropertiesConverter: JavaScriptConverter {
 public override object Deserialize(IDictionary < string, object > dictionary, Type type, JavaScriptSerializer serializer) {
  throw new NotImplementedException();
 }

 public override IDictionary < string, object > Serialize(object obj, JavaScriptSerializer serializer) {
  var jsonExample = new Dictionary < string,
   object > ();
  foreach(var prop in obj.GetType().GetProperties()) {
   //this object is nullable 
   var nullableobj = prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable < > );
   //check if decorated with ScriptIgnore attribute
   bool ignoreProp = prop.IsDefined(typeof(ScriptIgnoreAttribute), true);

   var value = prop.GetValue(obj, System.Reflection.BindingFlags.Public, null, null, null);
   int i;
   //Object is not nullable and value=0 , it is a default value for numeric types 
   if (!(nullableobj == false && value != null && (int.TryParse(value.ToString(), out i) ? i : 1) == 0) && value != null && !ignoreProp)
    jsonExample.Add(prop.Name, value);
  }

  return jsonExample;
 }

 public override IEnumerable < Type > SupportedTypes {
  get {
   return GetType().Assembly.GetTypes();
  }
 }
}
Nephritis answered 6/10, 2016 at 9:43 Comment(0)
D
0

Without changing toe DataContractSerializer

You can use ScriptIgnoreAttribute

[1] http://msdn.microsoft.com/en-us/library/system.web.script.serialization.scriptignoreattribute.aspx

Destinydestitute answered 25/3, 2013 at 14:15 Comment(1)
ScriptIgnore is useful if you want to always ignore a property, but not if you want to only ignore properties with null values but include them if they have a real value.Bagdad

© 2022 - 2024 — McMap. All rights reserved.