C# data contract for complex JSON object

后端 未结 3 1612
暗喜
暗喜 2021-01-21 11:32

This is probably something really simple and I looked everywhere and tried everything I could come up with. So I apologize if this is a simple search and I was just looking for

相关标签:
3条回答
  • 2021-01-21 11:54

    Use Json2CSharp.com to make sure you have everything correct:

     public class Datum
    {
    public string data1 { get; set; }
    public string data2 { get; set; }
    public string data3 { get; set; }
    public string connectorType { get; set; }
    public string sourceUri { get; set; }
    public string destinationUri { get; set; }
    public string rails { get; set; }
    public string data6 { get; set; }
    public string groupId { get; set; }
    public string failbackAction { get; set; }
    public string normal { get; set; }
    public string failoverAction { get; set; }
    public string artifactId { get; set; }
    public string normalState { get; set; }
    public string instanceId { get; set; }
    }
    
    public class RootObject
    {
    public string appname { get; set; }
    public string key { get; set; }
    public List<Datum> data { get; set; }
    public string updateId { get; set; }
    public string updateTS { get; set; }
    public string creationUser { get; set; }
    }
    
    0 讨论(0)
  • 2021-01-21 11:55

    Another option is to use the dynamic keyword. You could use a list of this type for data (per below).

    [DataContract]
    public class Update_DB
    {
        [DataMember(Name = "appname", IsRequired = true)]
        public string appname { get; set; }
        [DataMember]
        public string key { get; set; }
    
        [DataMember(Name = "data", IsRequired = true)]
        public List<dynamic> data { get; set; }
    
        [DataMember]
        public string updateId { get; set; }
        [DataMember]
        public string updateTS { get; set; }
        [DataMember]
        public string creationUser { get; set; }
    }
    

    From there, you could use the object by deserializing with JSON.Net, and access into the dynamic data object (assuming you know something about the shape of this dynamic object). Something like below will work based on the input string from the original post.

    Update_DB dataObj = JsonConvert.DeserializeObject<Update_DB>(objectJSON);
    string test = dataObj.data[1].connectorType; //evaluates to "webserver-to-appserver"
    
    0 讨论(0)
  • 2021-01-21 12:00

    Under normal circumstances, you could define your data property as a List<Dictionary<string, string>>, like so:

        [DataMember(Name = "data", IsRequired = true)]
        public List<Dictionary<string, string>> data { get; set; }
    

    Then you would be able to serialize and deserialize it successfully with Json.NET. Unfortunately, one of your data objects has duplicated keys:

      {
         "groupId":"group1",
         "failbackAction":"null",
         "normal":"null",
         "failoverAction":"null",
         "failbackAction":"null",
         "failoverAction":"null",
         "artifactId":"mywebserver",
         "normalState":"null"
      },
    

    Using duplicated keys is not recommended by the JSON standard, which states:

    When the names within an object are not unique, the behavior of software that receives such an object is unpredictable.

    In addition, c# dictionaries of course do not support duplicated keys, and data contract serialization does not duplicated property names.

    However, it is possible to read a JSON object with duplicated keys using Json.NET's JsonReader and create a custom JsonConverter to handle duplicated keys.

    First, define the following class to replace JsonValue. JsonValue is a silverlight-specific class whose use has been deprecated in overall .Net:

    [JsonConverter(typeof(JsonValueListConverter))]
    public sealed class JsonValueList
    {
        public JsonValueList()
        {
            this.Values = new List<KeyValuePair<string, string>>();
        }
    
        public List<KeyValuePair<string, string>> Values { get; private set; }
    }
    
    class JsonValueListConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return typeof(JsonValueList).IsAssignableFrom(objectType);
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.Null)
                return null;
            var jsonValue = (existingValue as JsonValueList ?? new JsonValueList());
            if (reader.TokenType != JsonToken.StartObject)
                throw new JsonSerializationException("Invalid reader.TokenType " + reader.TokenType);
            while (reader.Read())
            {
                switch (reader.TokenType)
                {
                    case JsonToken.Comment:
                        break;
                    case JsonToken.PropertyName:
                        {
                            var key = reader.Value.ToString();
                            if (!reader.Read())
                                throw new JsonSerializationException(string.Format("Missing value at path: {0}", reader.Path));
                            var value = serializer.Deserialize<string>(reader);
                            jsonValue.Values.Add(new KeyValuePair<string, string>(key, value));
                        }
                        break;
                    case JsonToken.EndObject:
                        return jsonValue;
                    default:
                        throw new JsonSerializationException(string.Format("Unknown token {0} at path: {1} ", reader.TokenType, reader.Path));
                }
            }
            throw new JsonSerializationException(string.Format("Unclosed object at path: {0}", reader.Path));
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var jsonValue = (JsonValueList)value;
            writer.WriteStartObject();
            foreach (var pair in jsonValue.Values)
            {
                writer.WritePropertyName(pair.Key);
                writer.WriteValue(pair.Value);
            }
            writer.WriteEndObject();
        }
    }
    

    Notice the use of [JsonConverter(typeof(JsonValueListConverter))]. This specifies the use of a custom converter when serializing and deserializing JsonValueList.

    Next, define your Update_DB class as follows:

    [DataContract]
    public class Update_DB
    {
        [DataMember(Name = "appname", IsRequired = true)]
        public string appname { get; set; }
        [DataMember]
        public string key { get; set; }
    
        [DataMember(Name = "data", IsRequired = true)]
        public List<JsonValueList> data { get; set; }
    
        [DataMember]
        public string updateId { get; set; }
        [DataMember]
        public string updateTS { get; set; }
        [DataMember]
        public string creationUser { get; set; }
    }
    

    Now you will be able to serialize and deserialize your JSON successfully. Sample fiddle.

    Update

    If you do not have duplicated keys, you can define your class as follows:

    [DataContract]
    public class Update_DB
    {
        [DataMember(Name = "appname", IsRequired = true)]
        public string appname { get; set; }
        [DataMember]
        public string key { get; set; }
    
        [DataMember(Name = "data", IsRequired = true)]
        public List<Dictionary<string, string>> data { get; set; }
    
        [DataMember]
        public string updateId { get; set; }
        [DataMember]
        public string updateTS { get; set; }
        [DataMember]
        public string creationUser { get; set; }
    }
    

    And then the following:

    var collection = new Update_DB
    {
        data = new List<Dictionary<string, string>>
        {
            new Dictionary<string, string>
            {
                {"data1", "10551296"},
                {"data2", "TrainingIns"},
                {"data3", "Completed"},
            },
            new Dictionary<string, string>
            {
                {"connectorType", "webserver-to-appserver"},
                {"sourceUri", "data4"},
                {"destinationUri", "data5"},
            },
        },
    };
    
    string x = JsonConvert.SerializeObject(collection.data, Formatting.Indented);
    
    Console.WriteLine(x);
    

    Produces the output:

    [
      {
        "data1": "10551296",
        "data2": "TrainingIns",
        "data3": "Completed"
      },
      {
        "connectorType": "webserver-to-appserver",
        "sourceUri": "data4",
        "destinationUri": "data5"
      }
    ]
    

    Sample fiddle.

    0 讨论(0)
提交回复
热议问题