Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ...

like image 991
Shri Avatar asked Nov 10 '16 13:11

Shri


People also ask

How do you serialize a JSON object?

NET objects as JSON (serialize) To write JSON to a string or to a file, call the JsonSerializer. Serialize method. The JSON output is minified (whitespace, indentation, and new-line characters are removed) by default.

What is serialize and deserialize in JSON?

JSON is a format that encodes objects in a string. Serialization means to convert an object into that string, and deserialization is its inverse operation (convert string -> object).

What does it mean to serialize data JSON?

Json namespace provides functionality for serializing to and deserializing from JavaScript Object Notation (JSON). Serialization is the process of converting the state of an object, that is, the values of its properties, into a form that can be stored or transmitted.

What does Jsonconvert Deserializeobject do?

Deserializes the JSON to the specified . NET type. Deserializes the JSON to the specified . NET type using a collection of JsonConverter.


2 Answers

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.

like image 134
dbc Avatar answered Nov 13 '22 22:11

dbc


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; }
    }
like image 29
Yanga Avatar answered Nov 14 '22 00:11

Yanga