Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
176 views
in Technique[技术] by (71.8m points)

neo4jclient - Can Neo4j store a dictionary in a node?

I an working on c# and use neo4jclient. I know neo4jclient can create a node if I pass a class object to it (I have tried it) Now in my class I want to add a dictionary property, this doesn't work. My code:

 GraphClient client = getConnection();
 client.Cypher
       .Merge("(user:User { uniqueIdInItsApp: {id} , appId: {appId} })")
       .OnCreate()
       .Set("user = {newUser}")
       .WithParams(new
       {
           id = user.uniqueIdInItsApp,
           appId = user.appId,
           newUser = user
       })
       .ExecuteWithoutResults();

The User contains a property that is a Dictionary in C#. When executing the cypher it shows the error

MatchError: Map() (of class scala.collection.convert.Wrappers$JMapWrapper)

Can anyone help me?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

By default Neo4j doesn't deal with Dictionaries (Maps in Java) so your only real solution here is to use a custom serializer and serialize the dictionary as a string property...

The code below only works for the type given, and you'll want to do something similar so you can use the default handling where possible, and only use this converter for your type:

//This is what I'm serializing
public class ThingWithDictionary
{
    public int Id { get; set; }
    public IDictionary<int, string> IntString { get; set; }
}

//This is the converter
public class ThingWithDictionaryJsonConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var twd = value as ThingWithDictionary;
        if (twd == null)
            return;

        JToken t = JToken.FromObject(value);
        if (t.Type != JTokenType.Object)
        {
            t.WriteTo(writer);
        }
        else
        {
            var o = (JObject)t;
            //Store original token in a temporary var
            var intString = o.Property("IntString");
            //Remove original from the JObject
            o.Remove("IntString");
            //Add a new 'InsString' property 'stringified'
            o.Add("IntString", intString.Value.ToString());
            //Write away!
            o.WriteTo(writer);
        }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (objectType != typeof(ThingWithDictionary))
            return null;

        //Load our object
        JObject jObject = JObject.Load(reader);
        //Get the InsString token into a temp var
        var intStringToken = jObject.Property("IntString").Value;
        //Remove it so it's not deserialized by Json.NET
        jObject.Remove("IntString");

        //Get the dictionary ourselves and deserialize
        var dictionary = JsonConvert.DeserializeObject<Dictionary<int, string>>(intStringToken.ToString());

        //The output
        var output = new ThingWithDictionary();
        //Deserialize all the normal properties
        serializer.Populate(jObject.CreateReader(), output);

        //Add our dictionary
        output.IntString = dictionary;

        //return
        return output;
    }

    public override bool CanConvert(Type objectType)
    {
        //Only can convert if it's of the right type
        return objectType == typeof(ThingWithDictionary);
    }
}

Then to use in Neo4jClient:

var client = new GraphClient(new Uri("http://localhost:7474/db/data/"));
client.Connect();
client.JsonConverters.Add( new ThingWithDictionaryJsonConverter());

It'll then use that converter when it can.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...