1

I have the following class, whose fields I want to populate by deserializing a JSON file:

public class FirstThreeRandomProperties
{
   public List<string> extras1;
   public List<string> extras2;
   public List<string> extras3;
}

Unfortunately, the JSON I wish to deserialize has properties with variable names. I want to be able to deserialize the following JSON:

{
   'unknownName1': [ "A" ],
   'unknownName1': [ "A", "B", "C" ]
}

As you can see, the names of the properties are random, but the properties are always arrays of strings. I want to map the first three to the variables in ThreeExtras and throw the rest away (if there are more than three). I want this to be mapped to:

{
   'extras1': [ "A" ],
   'extras2': [ "A", "B", "C" ],
   'extras3': null
}

Is this possible?

EDIT: FirstThreeRandomProperties is actually a member of another object like so:

public class ParentObject
{
   // Other properties
   public FirstThreeRandomProperties extraProperties;
}

So I would prefer a solution that easily lets me fill ParentObject with extraProperties getting its values as described above.

Hradek1
  • 11
  • 2
  • 2
    You can go with parsing to `JToken`s and traversing that tree. – Alexey Rumyantsev Apr 12 '21 at 12:49
  • 1
    With identical key possible? if there are not indentical you can go for a dictionary and map afterward – Self Apr 12 '21 at 12:54
  • @AlexeyRumyantsev Do you have any recommendation how to implement this based on my edits? – Hradek1 Apr 12 '21 at 12:58
  • 1
    Does this answer your question? [Deserialize json with known and unknown fields](https://stackoverflow.com/questions/15253875/deserialize-json-with-known-and-unknown-fields) – Christoph Lütjen Apr 12 '21 at 13:08
  • @ChristophLütjen I like the solution using [JsonExtensionData]. Out of curiosity, I am wondering if it is possible to solve this problem without modifying the interface of FirstThreeRandomProperties? – Hradek1 Apr 12 '21 at 13:30
  • You could use a CustomConverter, see https://www.newtonsoft.com/json/help/html/CustomJsonConverterGeneric.htm or https://stackoverflow.com/questions/8030538/how-to-implement-custom-jsonconverter-in-json-net-to-deserialize-a-list-of-base – Christoph Lütjen Apr 12 '21 at 13:36
  • You could deserialize to a `Dictionary>` and take the first the values. While the .NET `Dictionary` is not documented to preserve order, in practice *as long as nothing is removed* the items will be in order of addition. Or you could make a [custom `JsonConverter`](https://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm) with the necessary deserialization logic. – dbc Apr 13 '21 at 21:00

1 Answers1

0

Here's how you can deserialize your json to your FirstThreeRandomProperties class :

var json = "{\"extras1\":[\"A\"],\"extras2\":[\"A\",\"B\",\"C\"],\"extras3\":null}";

var jObject = JObject.Parse(json);

var firstThreeRandomProperties = jObject.ToObject<FirstThreeRandomProperties>();

From the docs, this will create an instance of the specified .NET type. It will automatically try to map the first token to the first property of your class and so on. So for example, if your property is an object but the JToken is an array, the property will be null because it won't be able to do the mapping. If you need this method to be reliable, you have to be certain that each token of the JSON has the same type as the property in your class. Otherwise, you will have to loop through all the tokens and do the needed checks.

This will result into :

enter image description here

If you need to deserialize directly to your ParentObject class, the JSON should look like this :

{
  "extraProperties": {
    "extras1": [ "A" ],
    "extras2": [ "A", "B", "C" ],
    "extras3": null 
  }
}

and you can do :

jObject.ToObject<ParentObject>();

Otherwise, all you have to do is :

var parentObject = new ParentObject
{
    ExtraProperties = jObject.ToObject<FirstThreeRandomProperties>()
};
uodami
  • 81
  • 3