Deserialize JSON string embedded within JSON directly

拥有回忆 提交于 2020-05-16 04:07:11

问题


I'm using .netcore 3.1 and I'm using System.Text.Json for serialization and deserialization. I didn't know how to phrase my question precisely. I looked around but couldn't find a direct answer for my question.

Apologies if it's a duplicate.

This is a sample JSON response.

{
    "properties": {
        "subscriptionId": "sub1",
        "usageStartTime": "2015-03-03T00:00:00+00:00",
        "usageEndTime": "2015-03-04T00:00:00+00:00",
        "instanceData": "{\"Microsoft.Resources\":{\"resourceUri\":\"resourceUri1\",\"location\":\"Alaska\",\"tags\":null,\"additionalInfo\":null}}",
        "quantity": 2.4000000000,
        "meterId": "meterID1"
    }
}

I'm interested in directly parsing instanceData. If you observe closely, instanceData is an embedded JSON string.

{
    "Microsoft.Resources": {
        "resourceUri": "resourceUri1",
        "location": "Alaska",
        "tags": null,
        "additionalInfo": null
    }
}

Question:

Is it possible to parse this instanceData while the whole Json is being parsed? Can we add some Attributes to instanceData field for direct parsing? Right now, I'm accessing the string from the parsed model class and parsing instanceData separately.

This is what I'm doing right now (something like this):

JsonSerializer.Deserialize<MicrosoftResources>(parsedResponse.instanceData).

I have already built model classes for instanceData and other entities. Currently, instanceData is of type string in my root model class.


回答1:


I'm interested in directly parsing instanceData. If you observe closely, instanceData is an embedded JSON string

Is it possible to parse this instanceData while the whole Json is being parsed?

You can achieve above requirement by creating and using a custom converter, like below.

public class ResConverter : JsonConverter<InstanceData>
{
    public override InstanceData Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        //you can implement it based on your actual requirement
        //...

        string jsonData = reader.GetString();

        var instanceData = System.Text.Json.JsonSerializer.Deserialize<InstanceData>(jsonData);

        return instanceData;
    }

Model Classes

public class MyModel
{
    public Properties Properties { get; set; }
}

public class Properties
{
    public string SubscriptionId { get; set; }
    public DateTimeOffset UsageStartTime { get; set; }
    public DateTimeOffset UsageEndTime { get; set; }

    [JsonConverter(typeof(ResConverter))]
    public InstanceData InstanceData { get; set; }
    public double Quantity { get; set; }
    public string MeterId { get; set; }
}

public class InstanceData
{
    [JsonPropertyName("Microsoft.Resources")]
    public MicrosoftResources MicrosoftResources { get; set; }
}

public class MicrosoftResources
{
    public string ResourceUri { get; set; }
    public string Location { get; set; }
    public object Tags { get; set; }
    public object AdditionalInfo { get; set; }
}

Test code and result

var jsondata = "{\"Properties\":{\"SubscriptionId\":\"sub1\",\"UsageStartTime\":\"2015-03-03T00:00:00+00:00\",\"UsageEndTime\":\"2015-03-04T00:00:00+00:00\",\"InstanceData\":\"{\\u0022Microsoft.Resources\\u0022:{\\u0022ResourceUri\\u0022:\\u0022resourceUri1\\u0022,\\u0022Location\\u0022:\\u0022Alaska\\u0022,\\u0022Tags\\u0022:null,\\u0022AdditionalInfo\\u0022:null}}\",\"Quantity\":2.4,\"MeterId\":\"meterID1\"}}";

MyModel myModel = System.Text.Json.JsonSerializer.Deserialize<MyModel>(jsondata);




回答2:


If you can change the instanceData to Json instead of string like this.

{
    "properties": {
        "subscriptionId": "sub1",
        "usageStartTime": "2015-03-03T00:00:00+00:00",
        "usageEndTime": "2015-03-04T00:00:00+00:00",
        "instanceData": {"Microsoft.Resources":{"resourceUri":"resourceUri1","location":"Alaska","tags":null,"additionalInfo":null}},
        "quantity": 2.4000000000,
        "meterId": "meterID1"
    }
}

You can easily deserialize your Json using the example below.

Model Classes:

public partial class Properties
{
    [JsonPropertyName("properties")]
    public PropertiesClass PropertiesProperties { get; set; }
}

public partial class PropertiesClass
{
    [JsonPropertyName("subscriptionId")]
    public string SubscriptionId { get; set; }

    [JsonPropertyName("usageStartTime")]
    public DateTimeOffset UsageStartTime { get; set; }

    [JsonPropertyName("usageEndTime")]
    public DateTimeOffset UsageEndTime { get; set; }

    [JsonPropertyName("instanceData")]
    public InstanceData InstanceData { get; set; }

    [JsonPropertyName("quantity")]
    public double Quantity { get; set; }

    [JsonPropertyName("meterId")]
    public string MeterId { get; set; }
}

public partial class InstanceData
{
    [JsonPropertyName("Microsoft.Resources")]
    public MicrosoftResources MicrosoftResources { get; set; }
}

public partial class MicrosoftResources
{
    [JsonPropertyName("resourceUri")]
    public string ResourceUri { get; set; }

    [JsonPropertyName("location")]
    public string Location { get; set; }

    [JsonPropertyName("tags")]
    public object Tags { get; set; }

    [JsonPropertyName("additionalInfo")]
    public object AdditionalInfo { get; set; }
}

Usage:

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

class Program
{
    static void Main(string[] args)
    {
        // escaped version, just for demo
        var json =
            "{\r\n    \"properties\": {\r\n        \"subscriptionId\": \"sub1\",\r\n        \"usageStartTime\": \"2015-03-03T00:00:00+00:00\",\r\n        \"usageEndTime\": \"2015-03-04T00:00:00+00:00\",\r\n        \"instanceData\": {\"Microsoft.Resources\":{\"resourceUri\":\"resourceUri1\",\"location\":\"Alaska\",\"tags\":null,\"additionalInfo\":null}},\r\n        \"quantity\": 2.4000000000,\r\n        \"meterId\": \"meterID1\"\r\n    }\r\n}";
        var props = JsonSerializer.Deserialize<Properties>(json);

    }
}

Props will have all of the data. I hope this helps.



来源:https://stackoverflow.com/questions/61375112/deserialize-json-string-embedded-within-json-directly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!