Search code examples
c#jsonserializationautomapperjavascriptserializer

JavaScriptSerializer::Deserialize() removes hyperlinks


I have an AutoMapper mapping that looks like this

AutoMapper.Mapper.CreateMap<Dictionary<string, string>, DailyCheck>().ConvertUsing(
            x =>
            {
                JavaScriptSerializer serializer = new JavaScriptSerializer();
                return serializer.Deserialize<DailyCheck>(
                    Regex.Replace(serializer.Serialize(x),
                    "\\b(?<month>\\d{1,2})/(?<day>\\d{1,2})/(?<year>\\d{2,4})\\b",
                    "${day}-${month}-${year}", RegexOptions.None,
                    TimeSpan.FromMilliseconds(150))
                    );
            }
            );

What the code does is it takes a Dictionary and creates a Json object using the JavaScriptSerializer, I then pass that object to the Deserialize() function to map it to a strongly typed object of type DailyCheck.

The problem I am having is that when Deserealizing an http link gets removed and the property is set as null.

Besides the obvious question: "How do I fix this" I also want to ask why does the box standard function JavaScriptSerializer.Serialize() does NOT properly escape the link so it can be Deserialized() properly.

Here is the content of the DailyCheck class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Core.BusinessLayer
{
    /// <summary>
    /// Business Layer Interface of Daily Checks
    /// </summary>
    public class DailyCheck
    {
        /// <summary>
        /// Identifier of check
        /// </summary>
        public string Id { get; set; }
        /// <summary>
        /// The name of the check
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// Type of check, e.g. Stored procedure
        /// </summary>
        public string Type { get; set; }
        /// <summary>
        /// How often the check should be run
        /// </summary>
        public string Frequency { get; set; }
        /// <summary>
        /// What category does this check relate to?
        /// </summary>
        public string Category { get; set; }
        /// <summary>
        /// The working instruction associated with the check
        /// </summary>
        public string WorkingInstruction { get; set; }
        /// <summary>
        /// Check description
        /// </summary>
        public string Description { get; set; }
        /// <summary>
        /// Current status of check, E.g. Running/Failed/Succeeded
        /// </summary>
        public string Status { get; set; }
        /// <summary>
        /// The start date of the check, when it was made
        /// </summary>
        public DateTime StartDate { get; set; }
        /// <summary>
        /// The ending date for the check, only not nulled if it is completed
        /// </summary>
        public DateTime? EndDate { get; set; }
        /// <summary>
        /// Transi of last user to edit the check
        /// </summary>
        public string Transi { get; set; }
        /// <summary>
        /// Full name of the last user to edit check 
        /// </summary>
        public string UserName { get; set; }
        /// <summary>
        /// Last comment left for check
        /// </summary>
        public string Comment { get; set; }
        /// <summary>
        /// Iid of user to last sign off check
        /// </summary>
        public string SignedOffBy { get; set; }
        /// <summary>
        /// Id of latest run
        /// </summary>
        public string RunId { get; set; }
        /// <summary>
        /// Id of latest result
        /// </summary>
        public string ResultId { get; set; }
        /// <summary>
        /// Command associated with check
        /// </summary>
        public string Command { get; set; }
    }
}

EDIT: You can use the following Json object to test

{"id":"1","name":"TEST","type":"SP","frequency":"TD","category":"INT","working_instruction":"http://www.google.co.uk","description":"","command":"UPDATE","status":"NC","startdate":"","enddate":"","transi":"0000","runid":"","comment":"","signedoffby":"","resultid":"","username":""}

The raw value that appears in the watch window looks like this:

"{\"id\":\"335\",\"name\":\"TEST\",\"type\":\"SP\",\"frequency\":\"TD\",\"category\":\"INT\",\"working_instruction\":\"http://www.google.co.uk\",\"description\":\"\",\"command\":\"UPDATE\",\"status\":\"NC\",\"startdate\":\"\",\"enddate\":\"\",\"transi\":\"051w\",\"runid\":\"\",\"comment\":\"\",\"signedoffby\":\"\",\"resultid\":\"\",\"username\":\"\"}"

Solution

  • JavaScriptSerializer does its best to match property names to JSON fields, but a property named WorkingInstruction will not be populated from a field named working_instruction because of the underscore.

    Either rename the property to Working_Instruction, or annotate the entire class with [DataContract] and [DataMember(Name = "working_instruction)]" attributes.