复杂JSON对象的C#数据协定 [英] C# data contract for complex JSON object

查看:87
本文介绍了复杂JSON对象的C#数据协定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这可能真的很简单,我四处张望,尝试了所有可以想到的东西.因此,如果这是一个简单的搜索,我很抱歉,而我只是在寻找错误的内容.我也是数据合同和JSON的新手,所以这可能并不是那么复杂.

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 the wrong thing. I'm also new to data contracts and somewhat JSON so this probably isn't really that complex.

我正在创建一个API以提取JSON并将其存储在我们的数据库中. JSON如下所示:

I am creating an API to ingest JSON and store it in our database. The JSON will look something like this:

{
"appname" : "MyApp",
"key" : "Test123",
"data" :[
  { "data1" : "10551296", "data2" : "TrainingIns", "data3" : "Completed"}
  ,
  { "connectorType" : "webserver-to-appserver", "sourceUri" : "data4", "destinationUri" : "data5", "rails" : "N", "data6" : "null" }
  ,
  { "groupId" : "group1", "failbackAction" : "null", "normal" : "null", "failoverAction" : "null", "failbackAction" : "null", "failoverAction" : "null", "artifactId" : "mywebserver", "normalState" : "null" }
  ,
  { "instanceId" : "10551296abc" }]
,
"updateId" : "MyID",
"updateTS" : "30-AUG-16 05.56.24.000000000 AM" ,
"creationUser" : "APICall"
}

其中数据"字段将是一个数组,其中包含可变数量的JSON对象.我遇到的问题是由于未在数据"对象中获取数据或使其完全未定义.

Where the 'data' field will be an array with a variable amount of JSON objects. The issue I am having stems from either not getting data in the 'data' object or having it be completely undefined.

[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<JsonValue> data { get; set; }

    [DataMember]
    public string updateId { get; set; }
    [DataMember]
    public string updateTS { get; set; }
    [DataMember]
    public string creationUser { get; set; }
}

我已经收集到了我可能需要某种收集品吗?我已经尝试了所有可能找到的内容,但是我不知道如何为数据"定义数据成员. 当执行此操作时,以上合同为我提供了空数组:

I've gathered I might need a collection of some sort? I've tried everything I could find but I don't know how I should define the data member for 'data'. The above contract gives me empty arrays when I do this:

string x = JsonConvert.SerializeObject(collection.data);

我可以获得将数据"字段转换为字符串的其他所有字段.

I can get every other field I just need to turn the 'data' field into a string.

希望这是足够的信息.预先感谢您的帮助!

Hopefully that is enough info. Thanks in advance for any help!

推荐答案

在通常情况下,您可以将data属性定义为List<Dictionary<string, string>>,如下所示:

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; }

然后,您将可以使用Json.NET成功对其进行序列化和反序列化.不幸的是,您的数据对象之一具有重复的键:

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"
  },

JSON标准不建议使用重复的密钥,该声明指出:

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.

此外,c#字典当然不支持重复的键,并且数据协定序列化也不重复属性名称.

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

但是,可以使用Json.NET的 JsonReader 并创建一个自定义JsonConverter 来处理重复的密钥.

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.

首先,定义以下类来替换 JsonValue . JsonValue是Silverlight特定的类,其使用已在整个.Net中不推荐使用:

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();
    }
}

请注意使用 [JsonConverter(typeof(JsonValueListConverter))] .这指定在序列化和反序列化JsonValueList时使用自定义转换器.

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

接下来,如下定义您的Update_DB类:

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; }
}

现在,您将能够成功地序列化和反序列化JSON.样本小提琴.

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

更新

如果没有重复的键,则可以按以下方式定义您的类:

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; }
}

然后是以下内容:

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);

产生输出:

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

示例小提琴.

这篇关于复杂JSON对象的C#数据协定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆