Home > Back-end >  Is it possible to leave fields as raw text when deserializing?
Is it possible to leave fields as raw text when deserializing?

Time:09-29

I have json like this

{
    "guid": "b1e3c29f-066f-417b-b6b6-795ffae90f0a",
    "status": "complete",
    "type": "colors",    
    "results": {
        "events": [
            {
                "title": "event1",
                "other": {
                    "Red": "red",
                    "Green": "green",
                    "Blue": "blue"
                }
            },
            {
                "title": "event2",
                "other": {
                    "Yelow": "yellow",
                    "Orange": "orange"
                }
            }
        ]
    }
}

and classes for deserialization looks like this

public class Other
{
    public string Red { get; set; }
    public string Green { get; set; }
    public string Blue { get; set; }
    public string Yelow { get; set; }
    public string Orange { get; set; }
}

public class Event
{
    public string title { get; set; }
    public Other other { get; set; }
}

public class Results
{
    public List<Event> events { get; set; }
}

public class Root
{
    public string guid { get; set; }
    public string status { get; set; }
    public string type { get; set; }
    public Results results { get; set; }
}

When I deserialize this json with

var root = JsonConvert.DeserializeObject<Root>(JsonContent); 

everything works fine.

The problem is that the content of json section "Other" is changeable and I don't know its complete content.
Also I need to put this classes in database.

Is there a way to deserialize json section "Other" as one string field with raw text, and to look something like this:

public class Other
{
    public string AllFieldsFromOtherSectionAsRawText { get; set; }
}

CodePudding user response:

If you define your Other class like this:

public class Other
{
    public Other(string rawData)
    {
        Content = rawData;
    }
    public string Content { get; }
}

Then you can write a custom JsonConverter, which will treat your other nodes as string:

class ObjectToStringJsonConverter : JsonConverter
{
    private readonly Type theType;
    public ObjectToStringJsonConverter(Type type) => theType = type;

    public override bool CanConvert(Type objectType) => objectType == theType;

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        => throw new NotImplementedException();

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);
        if (token.Type == JTokenType.Object)
        {
            return Activator.CreateInstance(theType, args: token.ToString()); 
        }
        throw new NotSupportedException("The related node is not object");
    }
}

The only trick here is this line:

  • Activator.CreateInstance(theType, args: token.ToString());
  • Here we create a new Other instance and pass the string representation of the other node to the constructor.

Then the usage would look like this:

var root = JsonConvert.DeserializeObject<Root>(json, new[] { new ObjectToStringJsonConverter(typeof(Other)) });

CodePudding user response:

Isnt Other a Dictionary represenation?

Can't you write it as Dictionary

public Dictionary<String,String> other { get; set; }

Example:

    [Newtonsoft.Json.JsonExtensionData]
    public System.Collections.Generic.IDictionary<string, string> other

According to the documentation, you DeserializeObject on type Dictionary:

JsonConvert.DeserializeObject<Dictionary<string, string>>(json);

https://www.newtonsoft.com/json/help/html/DeserializeDictionary.htm

CodePudding user response:

Remove class Other from your code, and fix Event class

public class Event
{
    public string title { get; set; }
    [JsonProperty(PropertyName = "other")]
    public Dictionary<string, string> otherDict { get; set; }
    
    [Newtonsoft.Json.JsonIgnore]
    public IEnumerable<string> Other
    {
        get { return  otherDict.Values.ToArray(); }
    }

    [Newtonsoft.Json.JsonIgnore]
    public string AllFieldsFromOtherSectionAsRawText
    {
        get { return string.Join(",", Other);  }
    }
}

output

{
  "guid": "b1e3c29f-066f-417b-b6b6-795ffae90f0a",
  "status": "complete",
  "type": "colors",
  "results": {
    "events": [
      {
        "title": "event1",
        "other": {
          "Red": "red",
          "Green": "green",
          "Blue": "blue"
        },
        "AllFieldsFromOtherSectionAsRawText": "red,green,blue"
      },
      {
        "title": "event2",
        "other": {
          "Yelow": "yellow",
          "Orange": "orange"
        },
        "AllFieldsFromOtherSectionAsRawText": "yellow,orange"
      }
    ]
  }
}
  • Related