61674

How to add types information to JSON on serialization?

Question:

Angular requires Date objects in many places whereas JSON contains string representation of the date.

I want to add an array of properties which contain date values:

class Foo { public int IntProp {get;set;} public DateTime? Prop1 {get;set;} public DateTime Prop2 {get;set;} public Bar Bar {set;set;} } class Bar { public DateTime Prop {get;set;} public IEnumerable<DateTime?> Dates {get;set;} }

Foo should then be serialized like this:

{ "IntProp": 1, "Prop1": "...", "Prop2": "...", "Bar": { "Prop": "..." }, "<Dates>": [ "Prop1", "Prop2", "Bar.Prop", "Bar.Dates"] }

This allows me to automatically convert strings to date objects at the client side without testing every property whether it is convertible to Date like it is described in this <a href="https://stackoverflow.com/q/22435212/921054" rel="nofollow">question</a>.

I can collect the paths of date properties, but have no idea how to add populated array to the root.

Answer1:

You could convert to an intermediate <a href="http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Linq_JObject.htm" rel="nofollow">JObject</a> and add the property there. For instance, given the following converter:

public class PathLoggingDateTimeConverter : IsoDateTimeConverter { public const string DatePathPropertyName = "<Dates>"; readonly List<string> paths = new List<string>(); public override bool CanConvert(Type objectType) { if (!base.CanConvert(objectType)) return false; // Not for DateTimeOffset return objectType == typeof(DateTime) || objectType == typeof(DateTime?); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { base.WriteJson(writer, value, serializer); if (value != null) paths.Add(writer.Path); } public IList<string> Paths { get { return paths; } } }

You can do:

var root = new Foo { IntProp = 101, Prop1 = DateTime.Today.ToUniversalTime(), Prop2 = DateTime.Today.ToUniversalTime(), Bar = new Bar { Prop = DateTime.Today.ToUniversalTime(), Dates = new List<DateTime?> { null, DateTime.Today.ToUniversalTime() }, }, }; var converter = new PathLoggingDateTimeConverter(); var settings = new JsonSerializerSettings { Converters = new[] { converter } }; var obj = JObject.FromObject(root, JsonSerializer.CreateDefault(settings)); obj[PathLoggingDateTimeConverter.DatePathPropertyName] = JToken.FromObject(converter.Paths); Console.WriteLine(obj);

And the result is:

{ "IntProp": 101, "Prop1": "2016-10-25T04:00:00Z", "Prop2": "2016-10-25T04:00:00Z", "Bar": { "Prop": "2016-10-25T04:00:00Z", "Dates": [ null, "2016-10-25T04:00:00Z" ] }, "<Dates>": [ "Prop1", "Prop2", "Bar.Prop", "Bar.Dates[1]" ] }

Recommend

  • How enable GZIP compression for Spring HttpInvoker requests using Tomcat?
  • Json.net Add property to every class containing of a certain type
  • Using tablesorter custom parser only for filtering with Checkboxes - working example needed
  • Generic `vendors` mixin
  • How to denormalize nested list in R?
  • Get Quarters StartDate and EndDate from Year
  • MS SQL Server 2008 :Getting start date and end date of the week to next 8 weeks
  • Gson serializing Spring beans
  • React Native + Redux: What's the best and preferred navigation?
  • Aggregating two data frame columns without any existing pattern logic
  • data.table replicate rows after join?
  • Telegram bot API - Inline bot getting Error 400 while trying to answer inline query
  • Failed to find version-tag string. File must be updated
  • Alamofire and Reachability.swift not working on xCode8-beta5
  • several dataProvider per one Test in TestNG
  • Trying to string.Join an IList
  • How to specify input and output paths from cmd.exe for a PowerShell script?
  • Cannot get the UserManager class
  • Linq Merge lists
  • Convert SQLite database to XML
  • WPF Visiblity Binding to Boolean Expression with multiple Variables
  • Conversion from string “a” to type 'Boolean' is not valid
  • Spring Cloud Microservice Architecture Confusion
  • What does 'Language neutral' mean with regard to MAKELANGID?
  • Transactional Create with Validation in ServiceStack Redis Client
  • Set the selected item in dropdownlist in MVC3
  • Handling un-mapped Rest path
  • PHP - How to update data to MySQL when click a radio button
  • Align navbar back button on right side
  • swift auto completion not working in Xcode6-Beta
  • Excel - Autoshape get it's name from cell (value)
  • Window Size for Mac application
  • When should I choose bucket sort over other sorting algorithms?
  • Arrays break string types in Julia
  • VB.net deserialize, JSON Conversion from type 'Dictionary(Of String,Object)' to type '
  • Observable and ngFor in Angular 2
  • How to Embed XSL into XML
  • UserPrincipal.Current returns apppool on IIS
  • Conditional In-Line CSS for IE and Others?
  • How to push additional view controllers onto NavigationController but keep the TabBar?