Home > Back-end >  Is there a better way of decoding a json in C# where the name of the key varies?
Is there a better way of decoding a json in C# where the name of the key varies?

Time:09-04

I have a response from an external api that looks like this, if i send in properties like this:

{ 
 "color": "blue"
 "type": "dog"
}

and then if i enter an invalid value of any of these i get a short error message back and a longer description for the property i sent in that was wrong. So lets say i send in

{ 
 "color": "blue"
 "type": "banana"
}

I would get

{
  "problem": "invalid pet",
  "type": "banana is not a valid type of pet ",
  "messageProperties": [
   "color",
   "type" ]
}

Then if i send in

{
  "color": "banana",
  "type: "dog"
}

I would get

{
  "problem": "wrong pet color",
  "color": "banana is not a valid color for a pet",
   "messageProperties": [
   "color",
   "type" ]
}

Is there an easy way of handling this? The best solution i found so far feels overly complex. Is there a better way? I'm using .NET 6

    public class MyErrorClass
    {
        public MyErrorClass(string json)
        {
            
            dynamic data = JsonConvert.DeserializeObject<dynamic>(json);
            foreach (KeyValuePair<string, JToken> kw in ((JObject)((JContainer)data)))
            {
                switch (kw.Key)
                {
                    case "context":
                        context = (string) kw.Value;
                        break;
                    case "messageProperties":
                    {
                        List<JToken> children = kw.Value.Children().ToList();
                        messageVariables = children.Values<string>().ToList();
                        break;
                    }
                    default:
                        error = (string) kw.Value;
                        break;
                }
            }
        }
        public string context { get; set; }
        public string error { get; set; }
        public List<string> messageVariables { get; set; }
    }

CodePudding user response:

One approach is to use JsonExtensionData. For example:

class Resp
{
    public string Problem { get; set; }
    public List<string> MessageProperties { get; set; }
    [JsonIgnore]
    public Dictionary<string, string> Extras { get; set; }

    [JsonExtensionData]
    private IDictionary<string, JToken> _additionalData;
    [OnDeserialized]
    private void OnDeserialized(StreamingContext context)
    {
        Extras = _additionalData.ToDictionary(d => d.Key, d => d.Value.ToString());
    }
}

Or based on your example:

class MyErrorClass
{
    public string Problem { get; set; }
    public List<string> MessageProperties { get; set; }
    [JsonIgnore]
    public string Error { get; set; }

    [JsonExtensionData]
    private IDictionary<string, JToken> _additionalData;
    [OnDeserialized]
    private void OnDeserialized(StreamingContext context) => Error = _additionalData?.FirstOrDefault().Value?.ToString();
}

CodePudding user response:

Assuming that you are using Newtonsoft.JSON, you could import Newtonsoft.Json.Linq and perhaps use the following:

if(JObject.Parse(json).ContainsKey("problem"))

For objects you can also use something like:

.GetType().GetProperty("problem") // if != null, then property exists
  • Related