0

I am trying to serialise a DataSet (working with an old codebase and have to use a DataSet in this instance). I want to slim down the resulting JSON and remove null values and defaults (0 for int, false for bool). The following code does not exclude the int value in row 0 or the bool value in row 1, does anyone have any suggestions for how I can get this to work?

var dataSet = new DataSet();
dataSet.Tables.Add("MyTable");
dataSet.Tables[0].Columns.Add("StringValue", typeof(string));
dataSet.Tables[0].Columns.Add("IntValue", typeof(int));
dataSet.Tables[0].Columns.Add("BoolValue", typeof(bool));

var row = dataSet.Tables[0].NewRow();
row["StringValue"] = "Hello";
row["IntValue"] = 0;
row["BoolValue"] = true;
dataSet.Tables[0].Rows.Add(row);

row = dataSet.Tables[0].NewRow();
row["StringValue"] = null;
row["IntValue"] = 123;
row["BoolValue"] = false;
dataSet.Tables[0].Rows.Add(row);

var settings = new JsonSerializerSettings()
{
    NullValueHandling = NullValueHandling.Ignore,
    DefaultValueHandling = DefaultValueHandling.Ignore,
    Formatting = Formatting.Indented
};

Console.WriteLine(JsonConvert.SerializeObject(dataSet, settings));

/*OUTPUT:

{
  "MyTable": [
    {
      "StringValue": "Hello",
      "IntValue": 0,
      "BoolValue": true
    },
    {
      "IntValue": 123,
      "BoolValue": false
    }
  ]
}

*/
3
  • The issue here is that (especially for columns whose data type is a value type) there is a difference between a datarow cell with default value, and a datarow cell with no value. A cell with no value will have DataRow.IsNull(i) == true. A row with default value will have DataRow.IsNull(i) == false and `DataRow[i] returning a boxed default value. If you skip default values when serializing (especially for value types) you will lose that distinction. Commented Dec 19, 2024 at 22:53
  • In my case (and probably most cases) that distinction is not necessary. For example, when reading values back from the deserialised DataSet into a c# object: a number that is null, 0 or doesn't exist in the DataRow should all result in the value of 0 for that number. The length of the serialised JSON matters in this case for performance reasons, so I might as well leave out any values that are null or empty as I can default them. Commented Dec 20, 2024 at 9:58
  • Can you change the JSON format? And how many rows do your tables have? If your tables have many rows, it might be more efficient to write some schema at the beginning then write each row as a simple array. Commented Dec 20, 2024 at 20:22

1 Answer 1

0

the problem is that your values are not bool or int, they are "cell" in your DataRow. their default value is only null. in these cases I normally use the json to deal with type changes, for example you can define the class representing your row and they make a 2 way serialization to get what you looking for:

var row = dataSet.Tables[0].NewRow();
row["StringValue"] = "Hello";
row["IntValue"] = 0;
row["BoolValue"] = true;
dataSet.Tables[0].Rows.Add(row);

row = dataSet.Tables[0].NewRow();
row["StringValue"] = null;
row["IntValue"] = 123;
row["BoolValue"] = false;
dataSet.Tables[0].Rows.Add(row);

var settings = new JsonSerializerSettings()
{
    NullValueHandling = NullValueHandling.Ignore,
    DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate,
    Formatting = Newtonsoft.Json.Formatting.Indented
};

var json = JsonConvert.SerializeObject(dataSet, settings);
var myDataSet = JsonConvert.DeserializeObject<MySet>(json);

Console.WriteLine(JsonConvert.SerializeObject(myDataSet, settings));

class MyRecord { 
    public string StringValue { get; set; }
    public int IntValue { get; set; }
    public bool BoolValue { get; set; }
}
class MySet {
    public List<MyRecord> MyTable { get; set; }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. The main aim here is to reduce the size of the resulting JSON. I wonder is there a custom class I could write to determine the underlying data types of the DataCells?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.