3

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.

enter image description here

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

1
  • I tried a List of Dictionaries and that populated the results., but it does not use your class. Commented Sep 2, 2020 at 23:56

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

In a perfect world yes it would look like your example. However, I do not control that world and it gets worse. This is a small extract of about 100 fields and on top of that some are nested. In this imperfect world your solution is clean enough and I can generate it for the needed fields fairly easily. thx
@azpc -- It really can be frustrating working with other people's data. Especially when they didn't know what they were doing :) Been there many times. Good luck to you!
1

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());

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.