Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从JSON字符串获取动态键的值_C#_Json_Json.net - Fatal编程技术网

C# 从JSON字符串获取动态键的值

C# 从JSON字符串获取动态键的值,c#,json,json.net,C#,Json,Json.net,我有这个json字符串,我想得到每条记录的第四行(iValue,sValue)。 这里我的问题是每个记录的键都不同(基于值的数据类型) 有没有办法在C#上这样做 以下是一个例子: { "data": [ { "pKey": "0", "Entity": "tableName", "Attribute": "CID", "iValue": "13" }, {

我有这个json字符串,我想得到每条记录的第四行
(iValue,sValue)
。 这里我的问题是每个记录的键都不同(基于值的数据类型)

有没有办法在C#上这样做

以下是一个例子:

{ "data": [
        {
          "pKey": "0",
          "Entity": "tableName",
          "Attribute": "CID",
          "iValue": "13"
        },
        {
          "pKey": "0",
          "Entity": "tableName",
          "Attribute": "username",
          "sValue": "test_user1"
        }] }

我会将其反序列化为支持这两种类型属性的对象,然后通过代码尝试解析整数或字符串(如果整数失败)

如果
属性
值为您提供了查找哪个整数的线索,您还可以使用它来避免每次都尝试解析整数

我不会每次都依赖于属性是“第四”属性,因为我假设这是外部数据,您可能无法控制这些属性是否每次(现在和将来)都以完全相同的顺序出现

  • 如果您不知道数据类型,那么可以使用对象来处理它
  • 将JSON字符串反序列化为具体类是一个好主意,以避免字符串操作错误

    public class Datum
    {
        public object pKey { get; set; }
        public string Entity { get; set; }
        public string Attribute { get; set; }
        public string iValue { get; set; }
        public string sValue { get; set; }
    }
    
    public class DataCollection
    {
        public List<Datum> data { get; set; }
    }
    
    public void Test()
    {
        var str = "{\"data\":[{\"pKey\":\"0\",\"Entity\":\"tableName\",\"Attribute\":\"CID\",\"iValue\":\"13\"},{\"pKey\":\"0\",\"Entity\":\"tableName\",\"Attribute\":\"username\",\"sValue\":\"test_user1\"}]}";
        var list = JsonConvert.DeserializeObject<DataCollection>(str);
        var keys = list.data.Select(x => x.pKey).ToList();
    }
    
    公共类数据
    {
    公共对象pKey{get;set;}
    公共字符串实体{get;set;}
    公共字符串属性{get;set;}
    公共字符串iValue{get;set;}
    公共字符串sValue{get;set;}
    }
    公共类数据收集
    {
    公共列表数据{get;set;}
    }
    公开无效测试()
    {
    var str=“{\'data\\”:[{\'pKey\':\'0\',\'Entity\':\'tableName\',\'Attribute\':\'CID\',\'iValue\':\'13\',{\'pKey\':'0\',\'Entity\':\'tableName\',\'Attribute\':'username\','sValue\':'test u user1\'}”;
    var list=JsonConvert.DeserializeObject(str);
    var keys=list.data.Select(x=>x.pKey.ToList();
    }
    

  • 另一个选项是反序列化为
    动态
    ,并检查:

    var json = "{\"data\":[{\"pKey\":\"0\",\"Entity\":\"tableName\",\"Attribute\":\"CID\",\"iValue\":\"13\"},{\"pKey\":\"0\",\"Entity\":\"tableName\",\"Attribute\":\"username\",\"sValue\":\"test_user1\"}]}";
    
    var result = JsonConvert.DeserializeAnonymousType<dynamic>(json, null);
    
    if (result.data != null)
    {
        for (var i = 0; i < result.data.Count; i++)
        {
            if (result.data[i]["iValue"] != null)
                // Parse iValue
            if (result.data[i]["sValue"] != null)
                // Parse sValue
    
        }
    
    }
    
    var json=“{\'data\\”:[{\'pKey\':\'0\',\'Entity\':\'tableName\',\'Attribute\':\'CID\',\'iValue\':\'13\',{\'pKey\':'0\',\'Entity\'tableName\',\'Attribute\'username\',\'sValue\':'test user1\';
    var result=JsonConvert.DeserializeAnonymousType(json,null);
    如果(result.data!=null)
    {
    对于(变量i=0;i
    您可以在ExpandooObject中加载Json

    var expConverter = new ExpandoObjectConverter();
    dynamic objList = JsonConvert.DeserializeObject<List<ExpandoObject>>(json, expConverter);
    
    var expConverter=new ExpandoObjectConverter();
    动态objList=JsonConvert.DeserializeObject(json,expConverter);
    

    然后,一旦你把它作为一个
    列表加载进去,你就可以把它当作一个字典来读了

        foreach(var obj in objList) 
        {
    //convert the object to a Dictionary and select the 4th element.
          var yourresult = (obj as IDictionary<string, object>).ElementAt(3);
        }
    
    foreach(对象列表中的变量obj)
    {
    //将对象转换为字典并选择第四个元素。
    var yourresult=(对象为IDictionary).ElementAt(3);
    }
    
    我的两分钱:

    将数组的每个对象作为
    KeyValuePair
    使用此解决方案,您始终可以知道指定了哪个属性(
    iValue
    sValue
    )。相反,如果使用同时具有两个属性名称的模型类,则当值为
    null
    (除非使用其他属性/类和自定义的
    JsonConverter
    )时,您将不知道指定了哪个属性

    编辑 正如提醒我的那样,
    JObject
    类实现了
    IDictionary
    。因此,在您的
    foreach
    中,您可以使用:

    if (element["iValue"] != null)
    {
        var propertyValue = element["iValue"].Value<string>();
    }
    if (element["sValue"] != null)
    {
        var propertyValue = element["sValue"].Value<string>();
    }
    
    // Or you can check the property name in the desidered position
    var propName = element.Properties().ElementAt(3).Name;
    
    if (propName == "iValue")
    {
        var propertyValue = keyValuePair["iValue"].Value<string>();
    }
    else if (propName == "sValue")
    {
        var propertyValue = keyValuePair["sValue"].Value<string>();
    }
    
    if(元素[“iValue”]!=null)
    {
    var propertyValue=元素[“iValue”].Value();
    }
    if(元素[“sValue”]!=null)
    {
    var propertyValue=元素[“sValue”].Value();
    }
    //或者,您可以在指定位置检查属性名称
    var propName=element.Properties().ElementAt(3).Name;
    如果(propName==“iValue”)
    {
    var propertyValue=keyValuePair[“iValue”].Value();
    }
    else if(propName==“sValue”)
    {
    var propertyValue=keyValuePair[“sValue”].Value();
    }
    

    当然,您可以优化此代码并检查空值。

    这是一个很大的实现,您必须为每个
    iValue
    fValue
    等实现此功能,但是,它加快了实现和使用。首先,这里是用法:

    string rawJson = "{\"data\":[{\"pKey\":\"0\",\"Entity\":\"tableName\",\"Attribute\":\"CID\",\"iValue\":\"13\"},{\"pKey\":\"0\",\"Entity\":\"tableName\",\"Attribute\":\"username\",\"sValue\":\"test_user1\"}]}";
    
    var values = JsonConvert.DeserializeObject<TakeData>(rawJson).Data.Select(v => v.PureData);
    
    以下是实施方案:

    class TakeData
    {
        public List<TakeItAll> Data { get; set; }
    }
    
    class TakeItAll
    {
    
        public int pKey { get; set; }
        public string Entity { get; set; }
        public string Attribute { get; set; }
    
        private int _iValue;
        public int iValue
        {
            get => _iValue;
            set
            {
                _iValue = value;
                PureData = new IntData { pKey = pKey, Entity = Entity, Attribute = Attribute, iValue = iValue };
            }
        }
    
        private string _sValue;
        public string sValue
        {
            get => _sValue;
            set
            {
                _sValue = value;
                PureData = new StrData { pKey = pKey, Entity = Entity, Attribute = Attribute, sValue = sValue };
            }
        }
    
        public IPureData PureData { get; private set; }
    
    }
    
    interface IPureData
    {
        int pKey { get; set; }
        string Entity { get; set; }
        string Attribute { get; set; }
    }
    
    class IntData : IPureData
    {
        public int pKey { get; set; }
        public string Entity { get; set; }
        public string Attribute { get; set; }
        public int iValue { get; set; }
    }
    
    class StrData : IPureData
    {
        public int pKey { get; set; }
        public string Entity { get; set; }
        public string Attribute { get; set; }
        public string sValue { get; set; }
    }
    

    每个记录是否只有
    iValue
    sValue
    ,或者是否有其他可能的键?根据,JSON对象是一组无序的名称/值对。那么,您真的希望每个
    “data”
    对象中的第四个值,不管它是哪个值?或者您是否希望名为
    “iValue”
    的值,无论它是否显示在第四位?
    sValue
    表示字符串,
    iValue
    表示整数,
    pValue
    表示十进制,
    fValue
    表示浮点,
    dValue
    表示日期和/或时间,
    bValue
    分别用于binary/varbinary。对-那么问题应该说明这一点。因此,您有一组固定的可能键,但比您显示的键更多。到目前为止,您需要扩展答案中给出的想法,以包括额外的键,但这应该不会太糟糕。@JoshuaPena如果您想强制使用模式,请使用JSON模式。JSON没有小数、浮点数、日期等,使用前缀是一个非常糟糕的主意。JSON也不需要属性/值结构——对象是字典。为什么要使用此表单而不是
    “myEntity”:{“Key”:0,“CID”:13,“username”,“test_user1”}
    ?JSON对象是字典。不需要反序列化到字典,它实现了
    IDictionary
    您是对的@PanagiotisKanavos。答案已更新。谢谢。
    string rawJson = "{\"data\":[{\"pKey\":\"0\",\"Entity\":\"tableName\",\"Attribute\":\"CID\",\"iValue\":\"13\"},{\"pKey\":\"0\",\"Entity\":\"tableName\",\"Attribute\":\"username\",\"sValue\":\"test_user1\"}]}";
    
    var values = JsonConvert.DeserializeObject<TakeData>(rawJson).Data.Select(v => v.PureData);
    
    foreach (var val in values)
    {
        if (val is IntData i)
        {
            int myInt = i.iValue;
            // use the rest of the properties
        }
        else if (val is StrData s)
        {
            string myStr = s.sValue;
            // use the rest of the properties
        }
    }
    
    class TakeData
    {
        public List<TakeItAll> Data { get; set; }
    }
    
    class TakeItAll
    {
    
        public int pKey { get; set; }
        public string Entity { get; set; }
        public string Attribute { get; set; }
    
        private int _iValue;
        public int iValue
        {
            get => _iValue;
            set
            {
                _iValue = value;
                PureData = new IntData { pKey = pKey, Entity = Entity, Attribute = Attribute, iValue = iValue };
            }
        }
    
        private string _sValue;
        public string sValue
        {
            get => _sValue;
            set
            {
                _sValue = value;
                PureData = new StrData { pKey = pKey, Entity = Entity, Attribute = Attribute, sValue = sValue };
            }
        }
    
        public IPureData PureData { get; private set; }
    
    }
    
    interface IPureData
    {
        int pKey { get; set; }
        string Entity { get; set; }
        string Attribute { get; set; }
    }
    
    class IntData : IPureData
    {
        public int pKey { get; set; }
        public string Entity { get; set; }
        public string Attribute { get; set; }
        public int iValue { get; set; }
    }
    
    class StrData : IPureData
    {
        public int pKey { get; set; }
        public string Entity { get; set; }
        public string Attribute { get; set; }
        public string sValue { get; set; }
    }
    
    class TakeItAll
    {
    
        public int pKey { get; set; }
        public string Entity { get; set; }
        public string Attribute { get; set; }
    
        private int _iValue;
        public int iValue
        {
            get => _iValue;
            set
            {
                _iValue = value;
                ValType = typeof(string);
            }
        }
    
        private string _sValue;
        public string sValue
        {
            get => _sValue;
            set
            {
                _sValue = value;
                ValType = typeof(int);
            }
        }
    
        public Type ValType { get; private set; }
    
    }