在 C# 中读取 AppInsights 的 JSON 输出

Read JSON output from AppInsights in C#

我想在 C# 控制台应用程序中读取 AppInsights API 输出。

WebClient wc = new WebClient();
wc.BaseAddress = "https://api.applicationinsights.io/v1/apps/AppInsighID/query?query=requests|where timestamp>= ago(1h)|limit 100";
wc.Headers.Add("Host", "api.applicationinsights.io");
wc.Headers.Add("x-api-key", "key");

string json = wc.DownloadString("");

JObject jsonObject = JObject.Parse(json);

//With this, i got values for Rows

var rowsObject = jsonObject["tables"][0]["rows"];

现在值在数组中,在 rowObject 下,那么如何读取呢?

我也想知道阅读json字符串时应该遵循的最佳实践

我可以看到这样的数据

{
"tables": [
    {
        "name": "PrimaryResult",
        "columns": [
            {
                "name": "timestamp",
                "type": "datetime"
            },
            {
                "name": "id",
                "type": "string"
            },
            {
                "name": "source",
                "type": "string"
            },
            {
                "name": "name",
                "type": "string"
            },
            {
                "name": "url",
                "type": "string"
            },
            {
                "name": "success",
                "type": "string"
            },
            {
                "name": "resultCode",
                "type": "string"
            },
            {
                "name": "duration",
                "type": "real"
            },
            {
                "name": "performanceBucket",
                "type": "string"
            },
            {
                "name": "itemType",
                "type": "string"
            },
            {
                "name": "customDimensions",
                "type": "dynamic"
            },
            {
                "name": "customMeasurements",
                "type": "dynamic"
            },
            {
                "name": "operation_Name",
                "type": "string"
            },
            {
                "name": "operation_Id",
                "type": "string"
            },
            {
                "name": "operation_ParentId",
                "type": "string"
            },
            {
                "name": "operation_SyntheticSource",
                "type": "string"
            },
            {
                "name": "session_Id",
                "type": "string"
            },
            {
                "name": "user_Id",
                "type": "string"
            },
            {
                "name": "user_AuthenticatedId",
                "type": "string"
            },
            {
                "name": "user_AccountId",
                "type": "string"
            },
            {
                "name": "application_Version",
                "type": "string"
            },
            {
                "name": "client_Type",
                "type": "string"
            },
            {
                "name": "client_Model",
                "type": "string"
            },
            {
                "name": "client_OS",
                "type": "string"
            },
            {
                "name": "client_IP",
                "type": "string"
            },
            {
                "name": "client_City",
                "type": "string"
            },
            {
                "name": "client_StateOrProvince",
                "type": "string"
            },
            {
                "name": "client_CountryOrRegion",
                "type": "string"
            },
            {
                "name": "client_Browser",
                "type": "string"
            },
            {
                "name": "cloud_RoleName",
                "type": "string"
            },
            {
                "name": "cloud_RoleInstance",
                "type": "string"
            },
            {
                "name": "appId",
                "type": "string"
            },
            {
                "name": "appName",
                "type": "string"
            },
            {
                "name": "iKey",
                "type": "string"
            },
            {
                "name": "sdkVersion",
                "type": "string"
            },
            {
                "name": "itemId",
                "type": "string"
            },
            {
                "name": "itemCount",
                "type": "int"
            }
        ],
        "rows": [
            [
                "2020-01-16T07:07:35.8423912Z",
                "ID",
                "",
                "POST ",
                "https://",
                "True",
                "200",
                57.679,
                "<250ms",
                "request",
                "{\"Product Name\":\"Name\",\"Subscription Name\":\"Name\",\"Operation Name\":\"AdvancedSearch\",\"ApimanagementRegion\":\"Region\",\"ApimanagementServiceName\":\"Name\",\"Apim Request Id\":\"ID\",\"Request-Body\":\"{\\"P1\\":25,\\"P2\\":1,\\"P3\\":\\"All \\",\\"P4\\":\\"Earliest\\",\\"P5\\":\\"Extended\\",\\"P6\\":\\"All \\",\\"P6\\":\\"Latest\\",\\"queryList\\":[{\\"P7\\":\\"physics\\",\\"P8\\":\\"A1\\",\\"operator\\":\\"\\"}]}\",\"Cache\":\"None\",\"P9\":\"195.43.22.145\",\"API Name\":\"Name\",\"HTTP Method\":\"POST\"}",
                "{\"Response Size\":776,\"Request Size\":1092,\"Client Time (in ms)\":0}",
                "POST ",
                "ID",
                "ID",
                "",
                "",
                "",
                "1",
                "",
                "",
                "PC",
                "",
                "",
                "0.0.0.0",
                "Milan",
                "Milan",
                "Italy",
                "",
                "Value1",
                "Value2",
                "ID1",
                "AppInsight Name",
                "Name",
                "apim:0.12.885.0",
                "ID",
                1
            ]
        ]
    }
]
}

您可以反序列化 Json 并获取行信息。例如,

var result = JsonConvert.DeserializeObject<RootObject>(str);
var rowData = result.tables.SelectMany(x=>x.rows.SelectMany(c=>c));

如果您不想展平结果,您可以使用

var rowData = result.tables.SelectMany(x=>x.rows.Select(c=>c));

其中 RootObject 定义为

public class Column
{
    public string name { get; set; }
    public string type { get; set; }
}

public class Table
{
    public string name { get; set; }
    public List<Column> columns { get; set; }
    public List<List<string>> rows { get; set; }
}

public class RootObject
{
    public List<Table> tables { get; set; }
}

如果您打算消除空值,可以使用 Linq

过滤掉它们
var rowData = result.tables.SelectMany(x=>x.rows.SelectMany(c=>c))
                           .Where(x=>!string.IsNullOrEmpty(x));

或者对于非 Flatten 结果

var rowData = result.tables.SelectMany(x=>x.rows.Select(c=>c))
                           .Where(x=>!string.IsNullOrEmpty(x.ToString()));

更新

根据评论,要检索信息并根据数组中值的位置将其解析为 Dto,您可以执行以下操作。如评论中所述,该属性也可用于处理内联 Json 属性。

您可以先定义一个属性,如下所示。

public class DtoDefinitionAttribute:Attribute
{

    public DtoDefinitionAttribute(int order)=>Order = order;
    public DtoDefinitionAttribute(int order,bool isJson,Type jsonDataType)
    {
        Order = order;
        JsonDataType = jsonDataType;
        IsJson = isJson;
    }
    public bool IsJson{get;} = false;
    public int Order{get;}
    public Type JsonDataType {get;}
}

然后,您可以使用数组中相应值的索引来装饰您的 Dto 属性。此外,如果 Json 字符串预期为 Json,那么您也可以使用属性来指示它,如 ClientTime 属性 中所示 例如,

public class Dto
{
    [DtoDefinition(0)]
    public DateTime CurrentDate{get;set;}
    [DtoDefinition(1)]
    public string ID{get;set;}
    [DtoDefinition(2)]
    public string Url{get;set;}
    [DtoDefinition(11,true,typeof(Response))]
    public Response Json1{get;set;}
}

public class Response
{
    [JsonProperty("Response Size")]
    public string ResponseSize{get;set;}

    [JsonProperty("Request Size")]
    public string RequestSize{get;set;}

    [JsonProperty("Client Time (in ms)")]
    public int ClientTime{get;set;}
}

现在您可以使用通过

获得的rowData结果
var listDto = new List<Dto>();
foreach(var row in rowData)
{
    listDto.Add(AssignValues(row));
}

其中 AssignValues 定义为

public Dto AssignValues(List<string> row)
{
    var dto = new Dto();
    var properties = typeof(Dto).GetProperties().Where(x=>x.GetCustomAttributes<DtoDefinitionAttribute>().Any());
    foreach(var property in properties)
    {
        var attribute = property.GetCustomAttribute<DtoDefinitionAttribute>();
        if(attribute.IsJson)
        {
            var jsonData = row[attribute.Order].ToString();
            var deserializedData = JsonConvert.DeserializeObject(jsonData,attribute.JsonDataType);
            property.SetValue(dto,deserializedData);
        }
        else
        {
            property.SetValue(dto,Convert.ChangeType(row[attribute.Order],property.PropertyType));
        }
    }
    return dto;
}

AssignValues方法使用反射读取Attributes并基于它创建Dto实例。如果它发现属性将其定义为 Json,那么它将反序列化 json 值并使用结果。

Demo Code