How can I serialize and deserialize a type with a string member that contains "raw" JSON, without escaping the JSON in the process

I want to Deserialize JSON into Object but I don't want to Deserialize nested JSON, nested of nested JSON should convert into JSON list (Please check "My expected output" for clear idea) ...

// Suppose I have below JSON data, Here I have nested JSON for "Address" entity

String jsonEmployees =
"{"Employees":
[{"EmpId":1, "EmpName":"ABC", "Address":[{"AddressId":1, "Address":"Something"},{"AddressId":2, "Address":"Anything"}]},
{"EmpId":2, "EmpName":"XYZ", "Address":[{"AddressId":1, "Address":"Something"},{"AddressId":2, "Address":"Anything"}]}]
}"

public class Employee
{
    public int EmpId { get; set; }
    public string EmpName { get; set; }
    // **Note** : I'm not using List<Address> data type for Address, instead of I want list of address in JSON string
    public string Address { get; set; }
}

public class RootObject
{
    public List<Employee> Employees { get; set; }
}

var Employees = JsonConvert.DeserializeObject<RootObject>(jsonEmployees);

// My expected output

Employees[0].EmpId = 1;
Employees[0].EmpName = "ABC";
Employees[0].Address = "[{"AddressId":1, "Address":"Something"},{"AddressId":2, "Address":"Anything"}]";

Employees[1].EmpId = 2;
Employees[1].EmpName = "XYZ";
Employees[1].Address = "[{"AddressId":1, "Address":"Something"},{"AddressId":2, "Address":"Anything"}]";

Please suggest me the best way to solve this issue ...


Your question is, How can I serialize and deserialize a type with a string member that contains "raw" JSON, without escaping the JSON in the process?

This can be done via a custom JsonConverter that reads and writes raw JSON using JsonWriter.WriteRawValue() and JRaw.Create():

public class RawConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var raw = JRaw.Create(reader);
        return raw.ToString();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var s = (string)value;
        writer.WriteRawValue(s);
    }
}

Then apply it to your type as follows:

public class Employee
{
    public int EmpId { get; set; }
    public string EmpName { get; set; }
    // **Note** : I'm not using List<Address> data type for Address, instead of I want list of address in JSON string
    [JsonConverter(typeof(RawConverter))]
    public string Address { get; set; }
}

public class RootObject
{
    public List<Employee> Employees { get; set; }
}

Sample fiddle.

Note that the raw JSON string must represent valid JSON. If it does not, then the JSON created will be unreadable. If you want to guarantee that the JSON literal is valid, you can keep the JSON in a parsed state internally:

public class Employee
{
    public int EmpId { get; set; }
    public string EmpName { get; set; }

    [JsonProperty("Address")]
    JToken AddressToken { get; set; }

    [JsonIgnore]
    public string Address
    {
        get
        {
            if (AddressToken == null)
                return null;
            return AddressToken.ToString(Formatting.Indented); // Or Formatting.None if you prefer
        }
        set
        {
            if (value == null)
                AddressToken = null;
            else
                // Throw an exception if value is not valid JSON.
                AddressToken = JToken.Parse(value);
        }
    }
}

A converter is not needed for this implementation.


I think you will have to rebuild your list of Employees :

        RootObject Employees = JsonConvert.DeserializeObject<RootObject>(jsonEmployees);

        List<Employee> EmployeesNew = new List<Employee>();

        foreach (var item in Employees.Employees)
        {
            string StringAddress = JsonConvert.SerializeObject(item.Address, Formatting.None, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
            EmployeesNew.Add(new Employee { EmpId = item.EmpId, EmpName = item.EmpName, AddressString = StringAddress });

        }

Your class:

    public class Employee
    {
        public int EmpId { get; set; }
        public string EmpName { get; set; }
        // **Note** : I'm not using List<Address> data type for Address, instead of I want list of address in JSON string
        public List<AddressItems> Address { get; set; }
        public string AddressString { get; set; }
    }

    public class RootObject
    {
        public List<Employee> Employees { get; set; }
    }

    public class AddressItems
    {
        public int AddressId { get; set; }
        public string Address { get; set; }
    }