如何独立于顶级节点名称提取JSON

时间:2018-11-07 14:21:26

标签: c# .net json azure json.net

我有一个无Azure服务器功能,用于接收JSON有效负载并处理包含的记录。该功能可以很好地完成预期的工作,除了包装节点名称无关紧要。例如:

{
   "Wrapper": [{
        "Field1": "Apple",
        "Field2": "Peach",
        "Field3": "########5",
        "Field4": "Kiwi",
    }]
}

应以与以下相同的方式处理:

{
    "OtherWrapperName": [{
        "Column1": "Apple",
        "Something": "Peach",
        "SomethingElse": "Banana",
        "Field4": "Kiwi"
    }]
}

现在,似乎可以将顶级节点称为“包装器”。这是我的尝试(已删除一些代码,因为此示例不需要这样做):

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    string InputData = await req.Content.ReadAsStringAsync();
    var inputData = JsonConvert.DeserializeObject<ItemsPayload>(InputData);

    var propertiesLookup = new Dictionary<string, ItemUpdate>();
    var propertiesRequest = new PropertySearchRequest { Registry = new List<RequestPropertySearch>() };


    int recordCounter = 0;
    foreach (var item in inputData.Wrapper)
    {
        foreach (var kvp in item.Where(property => property.Value.StartsWith("@!!!@")))
        {
            propertiesLookup[recordCounter.ToString() + "|" + kvp.Value] = new ItemUpdate
            {
                Properties = item,
                UpdateKey = kvp.Key
            };
            propertiesRequest.Registry.Add(new RequestPropertySearch
            {
                Token = kvp.Value
            });
            recordCounter++;
        }

    }

    var intermediateRequest = JsonConvert.SerializeObject(propertiesRequest, Formatting.Indented);
    HttpResponseMessage response = MakeRequest(serviceUrl, intermediateRequest, securityHeaderName, securityHeaderValue);

    var responseBodyAsText = response.Content.ReadAsStringAsync();
    var intermediateData = JsonConvert.DeserializeObject<PropertySearchResponse>(responseBodyAsText.Result);
    recordCounter = 0;
    foreach (var item in intermediateData.Registry)
    {
        if (item.Value != null)
        {
            var itemToUpdate = propertiesLookup[recordCounter.ToString() + "|" + item.Token];
            itemToUpdate.Properties[itemToUpdate.UpdateKey] = item.Value;
            if (directive.ToLower() == "s")
            {
                itemToUpdate.Properties[$"@{itemToUpdate.UpdateKey}"] = item.Token;
            }
            // recordCounter++;
        }
        recordCounter++;
    }

    var result = JsonConvert.SerializeObject(inputData, Formatting.Indented);


    //return req.CreateResponse(HttpStatusCode.OK, "");
    return new HttpResponseMessage()
    {
        Content = new StringContent(result, System.Text.Encoding.UTF8, "application/json")
    };
}

型号:

public class ItemsPayload
{
    //public string Directive { get; set; }

    public List<Dictionary<string, string>> Wrapper { get; set; }
}

public class PropertySearchRequest
{
    public List<RequestPropertySearch> Registry { get; set; }
}

public class RequestPropertySearch
{
    public string Token { get; set; }
}

public class PropertySearchResponse
{
    public List<ResponsePropertySearch> Registry { get; set; }
}

public class ResponsePropertySearch
{
    public string Token { get; set; }

    public string Value { get; set; }

    public string ProcessId { get; set; }

    public string Code { get; set; }

    public string Remote { get; set; }

    public string Message { get; set; }
}

public class ItemUpdate
{
    public Dictionary<string, string> Properties { get; set; }

    public string UpdateKey { get; set; }
}

我认为ItemsPayload类属性“ Wrapper”导致了这种情况,就好像您将其更改为其他内容并重命名了JSON中的节点一样,它可以正常工作,但是我希望它独立于顶级节点的名称。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

您可以为JsonConverter创建一个简单的ItemsPayload,以处理不同的包装器名称。

public class ItemsPayloadConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(ItemsPayload);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject obj = JObject.Load(reader);
        ItemsPayload payload = new ItemsPayload();
        // Get the first property of the outer JSON object regardless of its name
        // and populate the payload from it
        JProperty wrapper = obj.Properties().FirstOrDefault();
        if (wrapper != null)
        {
            payload.Wrapper = wrapper.Value.ToObject<List<Dictionary<string, string>>>(serializer);
        }
        return payload;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

然后,仅使用ItemsPayload属性为您的[JsonConverter]类添加注释,并且该属性无需对您的代码进行其他更改即可

[JsonConverter(typeof(ItemsPayloadConverter))]
public class ItemsPayload
{
    public List<Dictionary<string, string>> Wrapper { get; set; }
}

提琴:https://dotnetfiddle.net/9q4tgW