DotNet4Neo4j / Neo4jClient

.NET client binding for Neo4j
https://www.nuget.org/packages/Neo4jClient
Microsoft Public License
430 stars 146 forks source link

Custom JsonConverter implementation #446

Open flieks opened 2 years ago

flieks commented 2 years ago

Hi,

I am getting an error when this cypher is executed which without a custom JsonConverter worked fine.

                 var c = graphClient.Cypher
                        .Match("(q:Variable {Id: $id})")
                        .WithParam("id", variable.Id)
                        .Set("q = $variable")
                        .WithParam("variable", variable);

The error: Type mismatch for parameter 'variable': expected Map, Node or Relationship but was List<T> (line 2, column 9 (offset: 38)) "SET q = $variable" ^

The writeJSON implementation that executes fine:

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var twd = value as Variable;
            if (twd == null)
                return;

            JToken t = JToken.FromObject(value);
            if (t.Type != JTokenType.Object)
            {
                t.WriteTo(writer);
            }
            else
            {
                var o = (JObject)t;

                Variable variable = (Variable)value;

                //Store original token in a temporary var
                var dictionary = variable.TestProp;
                //Remove original from the JObject
                o.Remove("TestProp");

                foreach (var item in dictionary)
                {
                    //Add a new 'InsString' property 'stringified'
                    o.Add("TF_" + item.Key, item.Value);
                }

                //Write away!
                o.WriteTo(writer);
            }
        }

The TestProp property on class Variable:

    public class Variable
    {
      [Neo4jIgnore]
        public Dictionary<string, int> TestProp { get; set; } = new Dictionary<string, int>()
        {
            { "5", 60 },
            { "1", 600 }
        };
   }
cskardon commented 2 years ago

Sorry, I'm not 100% clear what you're saying with this - Is it that it doesn't work without custom code, or you need to use custom code to get it to work? What version of neo, what version of the client, bolt/http?

flieks commented 2 years ago

Hi @cskardon I am using client version 4.1.21 Neo4j version 4.4.3 using bolt

So i am using this custom JsonConverter (found the code from your answer on stackoverflow and i altered it so thanks for this.

I want to have a dictionary<string, int> on my c# model object and transform it to properties on the Node. So it goes inside WriteJson on c.ExecuteWithoutResultsAsync().Wait(); The code runs fine and then the JObject or JToken that is written with o.WriteTo(writer); is this (the 2 props with TF_ are injected coming from the dictionary)

{{
  "Id": "7d8823e6-1151-418d-908d-2f055e55f45d",
  "DateCreated": "2022-05-16T14:38:39.1513725Z",
  "DateUpdated": "2022-06-09T07:39:15.8640731Z",
  "DataType": 2,
  "Description": null,
  "Active": true,
  "Creator": null,
  "TF_5": 60,
  "TF_1": 600
}}  

but that results in a Type mismatch for parameter 'variable': expected Map, Node or Relationship but was List<T> (line 2, column 9 (offset: 38)) "SET q = $variable" ^ thrown by the await tx.CommitAsync();

readJson() is working fine as that just to return the Object (typed) and i use JsonConvert.DeserializeObject as the serializer input par is null so no problem.