-2

I have a class with a method that serializes an object into a string and then saves it as a JSON file and another method which deserializes that file back into its original object. The serialization method functions perfectly and outputs a file with all the data in the expected JSON format.

However, on deserialization, I get the following error:

Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported. Type 'Octopus.Client.Model.PersistenceSettingsResource'

After researching this, I found that the most common solution is to add [JsonConstructor] public PackagedProject() { } to the class I'm trying to deserialize to. Not only does this result in the same error, but I'm pretty sure I've used this exact method before without having to add a constructor, though I can't say for certain my memory isn't betraying me.

Here are the relevant parts of my code, only concerned with the class definition and file serialization and deserialization:

public class PackagedProject
{
    [JsonConstructor]
    public PackagedProject() { }
    public ProjectResource ProjectResource { get; set; }
    public VariableSetResource VariableSetResource { get; set; }
}

public class OctopusService
{
    public OctopusService(IConfiguration config)
    {
        var filename = "projects.json";
        SerializeProjects(packagedProject, filename);
        var deserializedProjects = DeserializedProjects(filename);
    }

    public void SerializeProjects(List<PackagedProject> projects, string filename)
    {
        var jsonString = JsonSerializer.Serialize(projects, new JsonSerializerOptions { WriteIndented = true });
        File.WriteAllText(filename, jsonString);
    }

    public List<PackagedProject> DeserializedProjects(string filename)
    {
        var currentDir = Directory.GetCurrentDirectory();
        var fileText = File.ReadAllText(currentDir + "/" + filename);

        var deserializedProjects = JsonSerializer.Deserialize<List<PackagedProject>>(fileText);
        return deserializedProjects;
    }
}

Additionally, the end of the error message is Type 'Octopus.Client.Model.PersistenceSettingsResource. I'm not sure what this means, but my best guess is that the Octopus.Client is the class type which is having trouble deserializing, but that doesn't make sense because I've specified that I want it to deserialize to List<PackagedProject>, not an Octopus.Client model.

derloopkat
  • 6,232
  • 16
  • 38
  • 45
  • Could you show code of your ProjectResource and VariableSetResource classes? And code of serialization into the file? – Timothy Jul 14 '23 at 10:34
  • @Timothy I've added serialization method and links to models to original post – Joe Pringle Jul 14 '23 at 10:49
  • 3
    It is because your class `ProjectResource` contains field of type `PersistenceSettingsResource` [see](https://github.com/OctopusDeploy/OctopusClients/blob/master/source/Octopus.Server.Client/Model/ProjectResource.cs#L74) – Ramin Rahimzada Jul 14 '23 at 10:54
  • @RaminRahimzada ProjectResource is a model imported from a package, so I don't have as much control over it as I do a class i've written myself. Any suggestions on how I can work around this? – Joe Pringle Jul 14 '23 at 10:59
  • 1
    @JoePringle: make a new, fresh model that is under your control. Make the two, the original model and the new model, convertible to and from. Serialize the new. – Wiktor Zychla Jul 14 '23 at 11:06
  • Sounds like you can fix this by [specifying a custom `[JsonConverter(...)]`](https://stackoverflow.com/questions/20995865/deserializing-json-to-abstract-class) on the `PersistenceSettingsResource` property – Mathias R. Jessen Jul 14 '23 at 12:38

1 Answers1

-1

As mentioned in the comments, my custom class PackagedProject contained a class imported from a package which was not compatible with System.Json's deserializer. I think Newtonsoft.json has the functionality to do this, but since i have to stick with System.Json, i had to replace the imported class with a new class that had a parameterless constructor.