Get dynamic key values ​​from a JSON string

I have this json line and I want to get the 4th line of (iValue, sValue)each record. My problem here is that the keys are different for each record (depending on the data type of the value).

Is there any way to do this in C #?

Here is an example:

{ "data": [
        {
          "pKey": "0",
          "Entity": "tableName",
          "Attribute": "CID",
          "iValue": "13"
        },
        {
          "pKey": "0",
          "Entity": "tableName",
          "Attribute": "username",
          "sValue": "test_user1"
        }] }
+4
source share
6 answers

Here is a kind of big implementation, you have to implement it for everyone iValue, fValueetc. However, this speeds up implementation and use. First of all, this use:

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

Now valuescontains a list. Here is a usage example for each of them:

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

And here is the implementation:

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

, . , TakeItAll ( ) . values .

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

}
+1

, , , , .

Attribute , , , .

, "" , , , , ( ).

0
  • , .
  • 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();
    }
    
0

- dynamic , :

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

    }

}
0

Json ExpandoObject

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

JSON ExpandoObject JSON.NET

, List<ExpandoObject>, .

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

:

KeyValuePair

var json = "your json here";

var root = JsonConvert.DeserializeObject<Root>(json);

foreach (var element in root.Data)
{
    //===================================================> Here using object because your value type change. You can change it to string if your value is always wrapped in a string (like "13")
    var keyValuePair = element.ToObject<Dictionary<string, object>>();

    //here, for each object of the 'data' array, you can check if the desidered property exists
    if (keyValuePair.ContainsKey("iValue"))
    {
        var propertyValue = keyValuePair["iValue"];
    }
    else if (keyValuePair.ContainsKey("sValue"))
    {
        var propertyValue = keyValuePair["sValue"];
    }

    // Or you can check the property name in the desidered position
    if (keyValuePair.Keys.ElementAt(3) == "iValue")
    {
        var propertyValue = keyValuePair["iValue"];
    }
    else if (keyValuePair.Keys.ElementAt(3) == "sValue")
    {
        var propertyValue = keyValuePair["sValue"];
    }
}

Where Rootis

class Root
{
    [JsonProperty("data")]
    public List<JObject> Data { get; set; }
}

With this solution, you can always find out which property ( iValueor sValue) is indicated. On the contrary, if you use a model class with property names, you do not know which property is indicated when the value null(unless you use additional properties / classes and custom JsonConverter).

Edit

As Panagiotis Kanavos reminded me, a class JObjectimplements IDictionary<string, JToken>. So inside foreachyou can use:

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

Of course, you can optimize this code and check for zeros.

0
source

Source: https://habr.com/ru/post/1692565/


All Articles