C# 从JSON字符串获取动态键的值
我有这个json字符串,我想得到每条记录的第四行C# 从JSON字符串获取动态键的值,c#,json,json.net,C#,Json,Json.net,我有这个json字符串,我想得到每条记录的第四行(iValue,sValue)。 这里我的问题是每个记录的键都不同(基于值的数据类型) 有没有办法在C#上这样做 以下是一个例子: { "data": [ { "pKey": "0", "Entity": "tableName", "Attribute": "CID", "iValue": "13" }, {
(iValue,sValue)
。
这里我的问题是每个记录的键都不同(基于值的数据类型)
有没有办法在C#上这样做
以下是一个例子:
{ "data": [
{
"pKey": "0",
"Entity": "tableName",
"Attribute": "CID",
"iValue": "13"
},
{
"pKey": "0",
"Entity": "tableName",
"Attribute": "username",
"sValue": "test_user1"
}] }
我会将其反序列化为支持这两种类型属性的对象,然后通过代码尝试解析整数或字符串(如果整数失败) 如果
属性
值为您提供了查找哪个整数的线索,您还可以使用它来避免每次都尝试解析整数
我不会每次都依赖于属性是“第四”属性,因为我假设这是外部数据,您可能无法控制这些属性是否每次(现在和将来)都以完全相同的顺序出现
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; }
}