0

*** Edit: Clarified there are two, separate JSON files ***

I have two classes:

public class Phone  
{
     public int PhoneId  { get; set; }
     public string Name { get; set; }
     public Manufacturer PhoneManufacturer { get; set; }
}

public class Manufacturer  
{
    public int ManId  { get; set; }
    public string Name  { get; set; }
}

And two JSON files containing data for both classes:

phones.json:

[
   {
       "phoneId" : 45,
       "name": "S20",
       "phoneManufacturer":16
   }
]

manufacturers.json:

[
   {
       "manId" : 16,
       "name": "Samsung"      
   }
]

I use the following code to deserialize the phones objects:

string jsonString = File.ReadAllText("phones.json");
return JsonSerializer.Deserialize<List<Phone>>(jsonString, new JsonSerializerOptions { PropertyNameCaseInsensitive = true})!;

I want that when deserializing the Phones JSON to List<Phone>, the resulting objects will have its PhoneManufacturer property populated with the actual Manufacturer object.

When running the deserialization with the default parameters, I get an error that JSON cannot convert the value in the PhoneManufacturer property to a Manufacturer object, which makes sense since this is the object Id, and not the object itself.

How can I achieve that?

Peter Csala
  • 17,736
  • 16
  • 35
  • 75
ml123
  • 1,059
  • 2
  • 12
  • 27

3 Answers3

2

You need to write a custom converter for manually mapping IDs to objects. There is a great series of Articles that cover this topic for both NewtonSoft & System.Text.Json: Working with JSON Series. The section labelled Multi-Value Type Collections is similar to what you are trying to do.

0

If you are using System.Text.Json, and you don't mind modifying the class to add a new constructor, this is quite achievable as long as you have a collection of manufacturers available to the Phone constructor. Something like:

[JsonConstructor]
public Phone(int phoneId, string name, int phoneManufacturer)
{
    PhoneId = phoneId;
    Name = name;
    if(!ManufacturerDictionary.Contains(phoneManufacture)) throw new Exception();
    PhoneManufacturer = ManufacturerDictionary.[phoneManufacturer];
} 
Andy Wynn
  • 1,171
  • 7
  • 11
0

you can try this code

var phonesJsonArr = JsonNode.Parse(phonesJson).AsArray();

var manufacturersJsonArr = JsonNode.Parse(manufacturersJson).AsArray();

    foreach (JsonNode node in phonesJsonArr)
    {
        var manId = node["phoneManufacturer"].GetValue<int>();
        node["PhoneManufacturer"] = new JsonObject
        {

            ["manId"] = manId,
            ["Name"] = manufacturersJsonArr.Where(ja => ja["manId"].GetValue<int>() == manId).Select(ja => ja["name"].GetValue<string>()).FirstOrDefault()

        };
         node.AsObject().Remove("phoneManufacturer");
     }

List<Phone> phones = phonesJsonArr.Deserialize<List<Phone>>(new JsonSerializerOptions { PropertyNameCaseInsensitive = true});
Serge
  • 40,935
  • 4
  • 18
  • 45