简体   繁体   中英

C# Deserialize JSON array with multiple objects

I'm taking in a JSON that I do not control in the format of this sample:

{
  "Transaction Information": [
    {
      "Type": "This is the Type"
    },
    {
      "Action": "No"
    },
    {
      "Owner": "Simpsons"
    },
    {
      "Buyer/Broker": "Y"
    },
    {
      "Compensation to Buyer": 3.0
    }
  ]
}

I want to deserialize it to a class such as:

public class Transaction
{
    [JsonProperty("Transaction Information")]
    public TransactionInformation[] TransactionInformation { get; set; }
}

public partial class TransactionInformation
{
    [JsonProperty("Type", NullValueHandling = NullValueHandling.Ignore)]
    public string Type { get; set; }

    [JsonProperty("Action", NullValueHandling = NullValueHandling.Ignore)]
    public string Action { get; set; }

    [JsonProperty("Owner", NullValueHandling = NullValueHandling.Ignore)]
    public string Owner { get; set; }

    [JsonProperty("Buyer/Broker", NullValueHandling = NullValueHandling.Ignore)]
    public string BuyerBroker { get; set; }

    [JsonProperty("Compensation to Buyer", NullValueHandling = NullValueHandling.Ignore)]
    public long? CompensationToBuyer { get; set; }
}

using the code

var obj = JsonConvert.DeserializeObject<Transaction>(json);

However that gives me a Transaction.TransactionInformation object with 5 records each with all 5 elements with each record having all null values except for one of the 5 elements.

在此处输入图片说明

Is there a simple way to to return all 5 elements in one record?

Is there a simple way to to return all 5 elements in one record?

Sure -- Just put each property in a single record:

var finalRecord = new TransactionInformation
{
    Type = obj.TransactionInformation.FirstOrDefault(x => !string.IsNullOrEmpty(x.Type))?.Type,
    Action = obj.TransactionInformation.FirstOrDefault(x => !string.IsNullOrEmpty(x.Action))?.Action,
    Owner = obj.TransactionInformation.FirstOrDefault(x => !string.IsNullOrEmpty(x.Owner))?.Owner,
    BuyerBroker = obj.TransactionInformation.FirstOrDefault(x => !string.IsNullOrEmpty(x.BuyerBroker))?.BuyerBroker,
    CompensationToBuyer = obj.TransactionInformation.FirstOrDefault(x => x.CompensationToBuyer.HasValue)?.CompensationToBuyer
};

That JSON data you are working with isn't in the most convenient format. In a perfect world it would look like this:

{
    "Transaction Information": [{
            "Type": "This is the Type",
            "Action": "No",
            "Owner": "Simpsons",
            "Buyer/Broker": "Y",
            "Compensation to Buyer": 3.0
        }
    ]
}

Then what you were doing would have worked fine and you wouldn't have to do this last step to normalize the data.

You can create a custom JsonConverter that enables you to hook into the deserialization for the type:

public class TransactionConverter : JsonConverter<Transaction>
{
    public override void WriteJson(JsonWriter writer, Transaction value, JsonSerializer serializer)
    {
    
    }

    public override Transaction ReadJson(JsonReader reader, Type objectType, Transaction existingValue,
        bool hasExistingValue, JsonSerializer serializer)
    {
    
        var rootChildren = JToken.ReadFrom(reader).First.Children();
        var item = new TransactionInformation();
        foreach (var child in rootChildren.Children())
        {
            item.Type ??= (string)child["Type"];
            item.Action ??= (string) child["Action"];
            item.BuyerBroker ??= (string)child["Buyer/Broker"];
            item.Owner ??= (string)child["Owner"];
            item.CompensationToBuyer ??= (long?)child["Compensation to Buyer"];
        }

        return new Transaction {TransactionInformation = new[] {item}};
    }

    public override bool CanRead => true;

}

and then call it:

var tx =  JsonConvert.DeserializeObject<Transaction>(str, new TransactionConverter());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM