将包含字符串数组的 Gremlin 结果映射到包含简单字符串属性的 C# 类

问题描述 投票:0回答:2

我在将 Gremlin 结果集映射到 C# 中的类时遇到问题。我正在尝试获取顶点和属性。这是代码:

public IList<T> All<T>() where T : class, new()
{
    Type type = typeof(T);
    string query = "g.V().hasLabel('" + type.Name.ToString().ToLower() + "').valueMap(true)";
    var resultSet = _gremlinClient.SubmitAsync<dynamic>(query).Result;
    List<T> list = JsonConvert.DeserializeObject<List<T>>(JsonConvert.SerializeObject(resultSet));
    return list;
}

这是我传递给这个通用方法的用户实体。

public class User
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
}

当我运行代码时,它在反序列化时抛出错误。

'解析值时遇到意外字符:[。路径 '[0].FirstName',第 1 行,位置 37。'

查看的时候,发现JSON字符串有带方括号的属性值,像这样:

[
  {
    "id": 0,
    "label": "user",
    "FirstName": [ "Azhar" ],
    "LastName": [ "Rahi" ]
  },
  {
    "id": 3,
    "label": "user",
    "FirstName": [ "John" ],
    "LastName": [ "Doe" ]
  }
]

你可以看到一些属性有方括号,比如

"FirstName":["Azhar"]
。我已经在没有方括号的情况下对其进行了测试,并且工作正常。所以错误的原因是因为字符串在 JSON 中表示为数组。

在上面的 JSON 字符串中,

id
label
是由 Gremlin.Net 自动生成的属性。剩下的其实是
User
对象属性。我不知道为什么 Gremlin 在为
Vertex
添加属性时添加括号,以及是否有可能避免它。

请提出任何解决方案,无论是在 Gremlin.Net 中还是通过某种方式更改 JSON 到类的映射。

c# json.net gremlinnet
2个回答
1
投票

所以,回顾一下:你有一些 JSON,其中一些属性是字符串数组,但你想在你的类中将它们建模为单个字符串,因为数组应该总是只有一个值。

Json.Net 默认情况下不会处理此映射,如您所见。但是您可以使用自定义

JsonConverter
来弥合差距。像这样定义转换器:

public class ArrayToSingleStringConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(string);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);
        switch (token.Type)
        {
            case JTokenType.Array:
                return (string)token.Children<JValue>().FirstOrDefault();
            case JTokenType.String:
                return (string)token;
            case JTokenType.Null:
                return null;
            default:
                throw new JsonException("Unexpected token type: " + token.Type);
        }
    }

    public override bool CanWrite => false;

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

然后,对于类中的每个字符串属性(可能是 JSON 中的数组),添加一个指定

[JsonConverter]
ArrayToSingleStringConverter
属性,如下所示:

public class User
{
    [JsonConverter(typeof(ArrayToSingleStringConverter))]
    public string FirstName { get; set; }

    [JsonConverter(typeof(ArrayToSingleStringConverter))]
    public string LastName { get; set; }
}

当你反序列化 JSON 时,它现在应该像你想要的那样工作。
演示小提琴:https://dotnetfiddle.net/Q9sGja

注意:如果你想以这种方式处理all你的字符串属性,你可以将转换器传递给

JsonConvert.DeserializeObject()
而不是用
[JsonConverter]
属性标记你的类:

List<T> list = JsonConvert.DeserializeObject<List<T>>(json, new ArrayToSingleStringConverter());

小提琴:https://dotnetfiddle.net/gcAqC5


0
投票

对于面临类似问题的任何人,这是我的解决方案。

ValueMap 方法返回值存储为数组的项目字典。

g.V().hasLabel('person').has('userId', '5').outE('friends').inV().hasLabel('person').valueMap('name','email','userId').fold()

输出:

[[name:[User 6],email:[[email protected]],userId:[6]]]

在.NET中获取数组的第一项需要处理

相反,我使用 value('name','email','userId') 方法明确指定我需要的属性,它只返回一个字符串数组,以及我指定的项目顺序。

g.V().hasLabel('person').has('userId', '5').outE('friends').inV().hasLabel('person').values('name','email','userId').fold()

输出:

[User 6,[email protected],6]

然后我可以简单地使用迭代器并将项目分配给我想要的 Strong-Type 对象。

var results = await gremlinClient.SubmitAsync<dynamic>("g.V().hasLabel('person').has('userId', '5').outE('friends').inV().hasLabel('person').values('name','email','userId').fold()");

var items = new string[3];
foreach (var result in results)
{
    int x = 0;
    foreach (var item in result)
    {
         items[x++] = (string)item;
    }
    friends.Add(new FriendsResponse
    {
          Name = items[0],
          Email = items[1],
          UserId = items[2]
    });
}
© www.soinside.com 2019 - 2024. All rights reserved.