1

I'm just starting to check how to serialize and deserialize using json for a project where I need to use ArangoDB.

At the moment, I have a test class AnoherTestPerson:

public class AnotherTestPerson
    {
        public AnotherTestPerson(int id, string fullname, int age)
        {
            this.Id = id;
            this.Fullname = fullname;
            this.Age = age;
        }

        public int Id { get; set; }
        public string Fullname { get; set; }
        public int Age { get; set; }
    }

Now, I need to cast the Id value to a string, because ArangoDB doesn't work when you pass a numerical value as the _key, so I'm guessing I have to do that from the serializer that the Arango driver uses, because in the project I'm going to work on, we won't have access to the classes of the entities we want to store on the data base.

Any help would be appreciated, as I'm still learning how serialization works with Json and C#.

Here's the rest of the code:

public static async Task Main(string[] args)
    {

        string connectionString = "private";

        var arango = new ArangoContext(cs:connectionString, settings:
            new ArangoConfiguration
            {
                Serializer = new ArangoNewtonsoftSerializer(CustomDataContractResolver.Instance)
                //Using custom contract resolver for automatically changing the Id name
                //from the object class to _key in the Json file
            }
        );
        await arango.Document.CreateAsync("TestDB", typeof(AnotherTestPerson).Name, testPerson);
    }

Here's the custom contract resolver. I tried changing the type of the property here but it didn't work.

public class CustomDataContractResolver : DefaultContractResolver
{
    public static readonly CustomDataContractResolver Instance = new CustomDataContractResolver();

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        if (property.PropertyName.Equals("Id", StringComparison.OrdinalIgnoreCase))
        {
            property.PropertyName = "_key";
            if(property.PropertyType == Type.GetType("System.Int32"))
            {
                property.PropertyType = Type.GetType("System.String");
            }
        }
        return property;
    }
}

EDIT

So checking the comment by SBFrancies, I implemented a basic JsonConverter:

public class ToStringJsonConverted : Newtonsoft.Json.JsonConverter
{
    public static readonly ToStringJsonConverted Instance = new ToStringJsonConverted();

    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
    {
        writer.WriteValue(value.ToString());
    }
}

and linked it to the custom ContractResolver:

public class CustomDataContractResolver : DefaultContractResolver
{
    public static readonly CustomDataContractResolver Instance = new CustomDataContractResolver();

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        if (property.PropertyName.Equals("Id", StringComparison.OrdinalIgnoreCase))
        {
            property.PropertyName = "_key";
            if(property.PropertyType == Type.GetType("System.Int32"))
            {
                property.Converter = ToStringJsonConverted.Instance;
            }
        }
        return property;
    }
}

It get's serialized as I wanted to, but the deserializing it's not working right now. I'll check how to read Json files and parse them for now.

Juan
  • 45
  • 1
  • 5
  • 1
    I think you have two options, write a custom converter or have a string property which is serialized. Look at the answers here: https://stackoverflow.com/questions/22354867/how-to-make-json-net-serializer-to-call-tostring-when-serializing-a-particular – SBFrancies Dec 20 '21 at 19:44

1 Answers1

0

I got the serializing and deserializing working, with help from @SBFrancies reference in the comments.

ContractResolver:

public class CustomDataContractResolver : DefaultContractResolver
{
    public static readonly CustomDataContractResolver Instance = new CustomDataContractResolver();

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        if (property.PropertyName.Equals("Id", StringComparison.OrdinalIgnoreCase))
        {
            property.PropertyName = "_key";
            if(property.PropertyType == Type.GetType("System.Int32"))
            {
                property.Converter = ToStringJsonConverted.Instance;
            }
        }
        return property;
    }
}

JsonConverter:

public class ToStringJsonConverted : Newtonsoft.Json.JsonConverter
{
    public static readonly ToStringJsonConverted Instance = new ToStringJsonConverted();

    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
    {
        return Int32.Parse((string)reader.Value);
    }

    public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
    {
        writer.WriteValue(value.ToString());
    }
}
Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
Juan
  • 45
  • 1
  • 5