遗传设置 JsonProperty (NewtonSoft) 以从 API 检索数据

Generically setting JsonProperty (NewtonSoft) for retreiving data from an API

我目前正在开展一个项目,我需要能够从 API 中检索数据,然后获取数据的某些部分。获取数据位一切顺利(使用 HttpClient),但现在我需要找到一种方法从该数据中获取某些元素。因此,我希望使用 NewtonSoft 将数据作为 classes.

下图显示了我的代码。 JsonProperty 应该是通用的,不幸的是这是不可能的,因为它会抛出错误“非静态字段需要对象引用”。 我希望它能够更改的原因是每个响应都具有相同的结构,但 JSON 中的名称不同,这意味着代码会中断。我读过有关 CustomPropertyResolvers 的资料,但我没能成功。

在下面的示例中,DataPointer class 中有一个“avg”值。这取决于被调用的端点。也有这样的情况,这个变量叫做“count”,是整数类型。我正在考虑借助可空变量来解决这个问题。但目前 JsonProperty 问题是主要问题。

任何人都可以给我一个例子或指出正确的方法来解决我的问题吗?

 public class DataMapper
{

    public async Task<string>MapData(HttpResponseMessage httpResponseMessage)
    {
        string responseContent = await httpResponseMessage.Content.ReadAsStringAsync();
        Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(responseContent);

        return null;
    }

    public class DataPointer
    {
        public double avg { get; set; }
    }

    public class Segment
    {
        public DateTimeOffset start { get; set; }
        public DateTimeOffset end { get; set; }

        [JsonProperty("requests/duration")]
        public DataPointer endValue { get; set; }
    }

    public class Value
    {
        public DateTime start { get; set; }
        public DateTime end { get; set; }
        public string interval { get; set; }
        public List<Segment> segments { get; set; }
    }

    public class Root
    {
        public Value value { get; set; }
    }
}

下面是我正在使用的响应示例。请注意,“requests/duration”部分是灵活的部分。这对于 API 中的每个端点都是不同的,这就是为什么我需要 JsonProperty 为 flexible/generic

    {
    "value": {
        "start": "2021-07-01T00:00:00.000Z",
        "end": "2021-07-04T00:00:00.000Z",
        "interval": "P1D",
        "segments": [
            {
                "start": "2021-07-01T00:00:00.000Z",
                "end": "2021-07-02T00:00:00.000Z",
                "requests/duration": {
                    "avg": 2072.02
                }
            },
            {
                "start": "2021-07-02T00:00:00.000Z",
                "end": "2021-07-03T00:00:00.000Z",
                "requests/duration": {
                    "avg": 4250.72
                }
            },
            {
                "start": "2021-07-03T00:00:00.000Z",
                "end": "2021-07-04T00:00:00.000Z",
                "requests/duration": {
                    "avg": 260.87
                }
            }
        ]
    }
}

试试这个。它在 VS 中测试并正常工作

var jsonOrig=...your json

 var deserializedJson = JsonConvert.DeserializeObject<Root>(jsonOrig);

            foreach (var dict in deserializedJson.value.segments)
            {

                var segment = new Segment();

                foreach (KeyValuePair<string, object> entry in dict)
                {
                    
                    switch (entry.Key)
                    {
                        case "start":
                            segment.start = (DateTime)entry.Value;
                            break;

                        case "end":
                            segment.end = (DateTime)entry.Value;
                            break;

                        default:

segment.endValue =JsonConvert.DeserializeObject<DataPointer>(entry.Value.ToString());
                            
                            break;
                    }

                    
                }
                deserializedJson.value.segmentsList.Add(segment);
            }

   deserializedJson.segments=null;

   return deserializedJson;

  public class Root
    {
        public Value value { get; set; }
    }

    public class Value
    {
        public DateTime start { get; set; }
        public DateTime end { get; set; }
        public string interval { get; set; }
        
        public List<Dictionary<string, object>> segments { get; set; }
        public List<Segment> segmentsList { get; set; } = new List<Segment>();
    }
    
    
    public class Segment
    {
        public DateTime start { get; set; }
        public DateTime end { get; set; }

        public DataPointer endValue { get; set; }
    }

    public class DataPointer
    {
        public double avg { get; set; }
    }

    

这可能是使用 NewtonsoftJson JsonExtensionData 属性.

的惯用方式

它捕获字典中任何未分配的属性,然后可以在 OnDeserialized 方法中检查和分配这些属性。

public class Test02 {
    public static void test(){
        var json = System.IO.File.ReadAllText("json.js");
        var res = JsonConvert.DeserializeObject<Root>(json);
    }
    public class DataPointer
    {
        public double avg { get; set; }
    }

    public class Segment
    {
        public DateTimeOffset start { get; set; }
        public DateTimeOffset end { get; set; }
        public DataPointer endValue { get; set; }


        [JsonExtensionData]
        private IDictionary<string, JToken> _additionalData;

        [OnDeserialized]
        private void OnDeserialized(StreamingContext context)
        {
            // "request/duration" is not deserialized to any property
            // and so it is added to the extension data dictionary

            JToken e;

            if(_additionalData.TryGetValue("requests/duration", out e)){
                endValue = e.ToObject<DataPointer>();
            }
        }
        public Segment()
        {
            _additionalData = new Dictionary<string, JToken>();
        }
    }

    public class Value
    {
        public DateTime start { get; set; }
        public DateTime end { get; set; }
        public string interval { get; set; }
        public List<Segment> segments { get; set; }
    }

    public class Root
    {
        public Value value { get; set; }
    }
}