Home > Software engineering >  In C#, can I edit/change the types in a json string?
In C#, can I edit/change the types in a json string?

Time:12-22

I have slightly annoying use case.

So, I am calling an API . The APi returns some json, which contains a json object with x amount of fields:

{
"status": "ok", 
"result": { 
     "firstprovider": [ .... ],
      "secondprovider": [ ...], 
      "thirdprovider": [ ... ] 
  }
 }

In this example, only three provider are returned, but I could get more or less than that, and their names may vary. It's quite important that I save those names. The "providers" inside of "result" are of the same type, so I can easily deserialize those to a certain model.

Now, I would normally expext "result" to be a json array of elements, so I could easily deserialize "result" into a List<LiveShopperEventModel>.

Currently, I made a hacky solution, creating a Dictionary<string,Provider> where the key is the name of the provider, and then I later use selectmany to flatten it into a list.

But, I was wondering if there exists some way in c#, that would allow me to convert the "result", into an array, which would make deserialization a lot simpler for me.

So, does anyone know of a way, or a resource that in c# can help in changing the types of json elements, and in this case, making a json object into a json array, with the fields becoming elements in the list?

Reproducing concept with minimal example

So, let's say my json looks like this:

{
"status": "ok", 
"result": { 
     "firstprovider": [ {"name":"John"}, {"car":"BMW"}, {"surname":"Johnson"} ],
      "secondprovider": [ {"name":"Zoe"}, {"car":"Ford"}, {"surname":"johnsøn"}], 
      "thirdprovider": [{"name":"Elliot"}, {"car":"Volkswagen"}, {"surname":"Jackson"} ] 
  }
 }

Then I can deserialize it as in the following code snippet:

string json = "{\r\n\"status\": \"ok\", \r\n\"result\": { \r\n     \"firstprovider\": [ {\"name\":\"John\"}, {\"car\":\"BMW\"}, {\"surname\":\"Johnson\", \"age\":30, \"car\":\"fast\"} ],\r\n      \"secondprovider\": [ {\"name\":\"Zoe\"}, {\"car\":\"Ford\"}, {\"surname\":\"johnsøn\", \"age\":31, \"car\":null}], \r\n      \"thirdprovider\": [{\"name\":\"Elliot\"}, {\"car\":\"Volkswagen\"}, {\"surname\":\"Jackson\", \"age\":32, \"car\":null} ] \r\n  }\r\n }\r\n";

// deserializing to a dictionary

var resultDict = JsonConvert.DeserializeObject<ResultModel>(json);

// and now flattening the structure, so that it is a list of "ProviderModel"
// this is the part that feels hacky to me


var providerModelList = resultDict.result.SelectMany(listOfEvents => {
    listOfEvents.Value.Select(Provider =>
    {
        Provider.provider = listOfEvents.Key;
        return Provider;
    }).ToList();
    return listOfEvents.Value;
}).ToList();
public class ResultModel
{
    [JsonProperty("result")]
    public Dictionary<string, List<ProviderModel>> result { get; set; }
}



public class ProviderModel
{
    public string provider { get; set; }

    public string name { get; set; }

    public string surname { get; set; }
         
}

The `selectmany" part feels hacky to me, since, i'm combining linq queries in a way that feels overly complicated

Instead, I think it would be much nicer, is the result class could just look like:

public class ResultModel
{
    [JsonProperty("result")]
    public List<ProviderModel> result { get; set; }
}

CodePudding user response:

you can try something like this

List<ProviderModel> providerModelList = ((JObject)JObject.Parse(json)["result"])
                                       .Properties()
                                       .Select(x => GetValues(x))
                                       .ToList();

public ProviderModel GetValues(JProperty jProp)
{
    var providerModel = new JObject(((JArray)jProp.Value)
    .Select(jo => ((JObject)jo).Properties().First()))
    .ToObject<ProviderModel>();

    providerModel.provider = jProp.Name;

    return providerModel;
}
  • Related