I have a problem with the default Serialization of my object.
public interface IUserProduct
{
public int Gramature { get; set; }
public ImageSource ProductImage { get; }
public string Name { get; }
public decimal Kcal { get; }
public decimal Carbohydrates { get; }
public decimal Fat { get; }
public decimal Proteins { get; }
public IProductDataTemplate ProductTemplate { get; set; }
}
The object has a property ImageSource
, unfortunately it is referring to itself, and I’m getting a System.Text.Json.JsonException: 'A possible object cycle was detected.
exception.
I have built a custom converter that is replacing a ImageSource
with a string but Im still getting the exception.
public override void Write(Utf8JsonWriter writer, IList<IUserProduct> value, JsonSerializerOptions options)
{
writer.WriteStartArray();
foreach (IUserProduct product in value)
{
writer.WriteStartObject();
writer.WriteString(nameof(product.Name), product.Name);
writer.WriteNumber(nameof(product.Kcal), product.Kcal);
writer.WriteNumber(nameof(product.Gramature), product.Gramature);
writer.WriteNumber(nameof(product.Proteins), product.Proteins);
writer.WriteNumber(nameof(product.Carbohydrates), product.Carbohydrates);
writer.WriteNumber(nameof(product.Fat), product.Fat);
string image = product.ProductImage.ToString();
writer.WriteString(nameof(product.ProductImage), image);
writer.WriteEndObject();
}
writer.WriteEndArray();
}
I have tried adding ReferenceHandler.Preserve
and ReferenceHandler.IgnoreCycles
but it doesn’t work neither.
This is a method that throws the exception:
private static readonly JsonSerializerOptions ProductSerializer = new JsonSerializerOptions()
{
Converters = { new JsonProductCustomConverter() }//this is my custom converter
};
private static void WriteProductsJSON(IUserProduct product, string fileName)
{
string json;
List<IUserProduct> products = new List<IUserProduct>();
if (File.Exists(Path.Combine(DataPath, fileName)))
{
json = File.ReadAllText(Path.Combine(DataPath, fileName));
products = System.Text.Json.JsonSerializer.Deserialize<List<IUserProduct>>(json, options: ProductSerializer);
}
products.Add(product);
json = System.Text.Json.JsonSerializer.Serialize(products, options: ProductSerializer);
File.WriteAllText(Path.Combine(DataPath, fileName), json);
}
What am I doing wrong? How can I serialize this ImageSource
as a string and remove the exception?
2
Answers
The problem was lying in the JsonConverter I had made, I did not understand how it worked correctly. CustomJsonConverter that inherits from
JsonConverter<T>
is not passing the whole object meant for serialization to thepublic override void Write(Utf8JsonWriter writer, IList<IUserProduct> value, JsonSerializerOptions options)
it only passes individual properties of that object to the method.In order to target a single property of type
T
to conversion, the type of that property should be specified in a custom-made converter. So, to custom serialize aImageSource
as astring
the converter should look like this in my case:Why don’t you add another property for the string and mark ProductImage with [JsonIgnore]?
Note: get with ImageSource.FromString is just an example. Use whatever method you have if you want to read the ImageSource back from your string.