c# - 使用 Json.NET 将嵌套 Firebase 数据库对象转换为 C# 对象

标签 c# json firebase firebase-realtime-database json.net

我需要使用 JSON.Net 库将 firebase-ish 数据结构转换为 C# 对象。

我将数据存储在 Firebase 数据库上,如下所示;

 {
    "PoolDatas": {
        "-LGGJGTAv_DPtzkmjIbl": {
            "CoinType": 2,
            "PoolType": 4,
            "Alias": "First Alias",
            "Address": "0xAE12EF212",
            "Alarms": {
                "-LGsdsdv_DPtzkmjIbl": {
                    "Threshold": {
                        "Type": 2,
                        "Val": 100
                    },
                    "AlarmType": 3
                },
                "-LBAsdsdv_DPtzkmjIbl": {
                    "Threshold": {
                        "Type": 1,
                        "Val": 1
                    },
                    "AlarmType": 2
                }
            }
        },
        "-LEAJGTAv_DPtzkmjIbl": {
            "CoinType": 1,
            "PoolType": 1,
            "Alias": "Second Alias",
            "Address": "0xAeeeEF212",
            "Alarms": {
                "-LGsdsdv_DPtzkmjIbl": {
                    "Threshold": {
                        "Type": 10,
                        "Val": 120
                    },
                    "AlarmType": 1
                },
                "-LBAsdsdv_DPtzkmjIbl": {
                    "Threshold": {
                        "Type": 1,
                        "Val": 250
                    },
                    "AlarmType": 2
                }
            }
        }
    }
 }

所有列表对象都有 firebase 生成的 ID。我无法将此数据映射到 C# 类,因为 firebase ID 不符合列表结构。

请在 C# 端查看我的模型;

public class PoolData
{
     public string FirebaseId{ get; set; }
     public string Alias { get; set; }
     public PoolType PoolType { get; set; } //enum
     public CoinType CoinType { get; set; } //enum
     public string Address { get; set; }
     public List<Alarm> Alarms { get; set; }
}

public class Alarm
{
     public string FirebaseId{ get; set; }
     public AlarmType AlarmType{ get; set; } //enum
     public Threshold Threshold { get; set; } //object
}

public class Threshold
{
     public ThresholdType Type{ get; set; } //enum
     public int Value { get; set; }
}

为了能够将 Firebase-ish json 转换为 C# 对象,我需要这样的 json;

{
   "PoolDatas": [
      {
         "FirebaseId": "-LGGJGTAv_DPtzkmjIbl",
         "CoinType": 1,
         "PoolType": 1,
         "Alias": "First Alias",
         "Alarms": [
            {
               "FirebaseId": "-LGsdsdv_DPtzkmjIbl",
               "Threshold": {
                  "Type": 1,
                  "Val": 1
               },
               "AlarmType": 1
            },
            {
               "FirebaseId": "-LBAsdsdv_DPtzkmjIbl",
               "Threshold": {
                  "Type": 1,
                  "Val": 1
               },
               "AlarmType": 2
            }
         ],
         "Address": "0xAE12EF212"
      },
      {
         "FirebaseId": "-LEAJGTAv_DPtzkmjIbl",
         "CoinType": 1,
         "PoolType": 1,
         "Alias": "First Alias",
         "Alarms": [
            {
               "FirebaseId": "-LGsdsdv_DPtzkmjIbl",
               "Threshold": {
                  "Type": 1,
                  "Val": 1
               },
               "AlarmType": 1
            },
            {
               "FirebaseId": "-LBAsdsdv_DPtzkmjIbl",
               "Threshold": {
                  "Type": 1,
                  "Val": 1
               },
               "AlarmType": 2
            }
         ],
         "Address": "0xAE12EF212"
      }
   ]
}

如何从第一个json中获取这个json?

我使用 JObject 循环尝试了几个递归过程,但没有成功。

提前致谢!

最佳答案

您可以将 JSON 反序列化为 Dictionary<string, PoolData> ,更改每个值,以便字典的键进入 FirebaseId 属性,然后将其放入数组中,如下所示:

class Origin
{
    public Dictionary<string, PoolData> PoolDatas { get; set; }
}

class Destination
{
    public PoolData[] PoolDatas { get; set; }
}


class Program
{
    static void Main(string[] args)
    {
        string json = File.ReadAllText("data.json");
        var data = JsonConvert.DeserializeObject<Origin>(json);
        var destination = new Destination();
        destination.PoolDatas = data.PoolDatas.Select(i =>
        {
            i.Value.FirebaseId = i.Key;
            return i.Value;
        }).ToArray();

    }
}

您需要安装并导入 Json.Net 包 using Newtonsoft.Json; .

编辑:正如评论中提到的,这不适用于嵌套对象。对于这种情况,也许您可​​以使用自定义序列化器,如下所示:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace ConsoleApp1
{

    public interface IFirebaseObject
    {
        string FirebaseId { get; set; }
    }

    public class PoolData
    {
        public string FirebaseId { get; set; }
        public string Alias { get; set; }
        public string Address { get; set; }
        [JsonConverter(typeof(MapToArrayConverter<Alarm>))]
        public List<Alarm> Alarms { get; set; }
    }

    public class Alarm: IFirebaseObject
    {
        public string FirebaseId { get; set; }
        public Threshold Threshold { get; set; } //object
    }

    public class Threshold
    {
        public int Value { get; set; }
    }

    class Origin
    {
        public Dictionary<string, PoolData> PoolDatas { get; set; }
    }

    class Destination
    {
        public PoolData[] PoolDatas { get; set; }
    }


    class Program
    {
        static void Main(string[] args)
        {
            string json = File.ReadAllText("data.json");
            var data = JsonConvert.DeserializeObject<Origin>(json);
            var destination = new Destination();
            destination.PoolDatas = data.PoolDatas.Select(i =>
            {
                i.Value.FirebaseId = i.Key;
                return i.Value;
            }).ToArray();
        }
    }


    public class MapToArrayConverter<T> : JsonConverter where T : IFirebaseObject
    {
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.StartObject)
            {
                JObject item = JObject.Load(reader);
                Dictionary<string, T> value = JsonConvert.DeserializeObject<Dictionary<string, T>>(item.ToString());
                // TODO also consider single values instead of lists
                return value.Select(i =>
                {
                    i.Value.FirebaseId = i.Key;
                    return i.Value;
                }).ToList();
            } else
            {
                return null;
            }
        }

        public override bool CanConvert(Type objectType)
        {
            // TODO validate the object type
            return true;
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            // TODO implement the reverse method to also write
            throw new NotImplementedException();
        }
    }
}

但是正如您所看到的,解决方案开始变得有些复杂。除非您需要对多种类型执行此操作,否则手动转换可能会更省时且更易于维护。

关于c# - 使用 Json.NET 将嵌套 Firebase 数据库对象转换为 C# 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51863103/

相关文章:

c# - Task.Factory.New vs Task.Run vs async/await,不阻塞 UI 线程的最佳方法

c# - 如何隐藏静态方法

java - 使用jackson解析时如何防止多余的字符串转换步骤?

c# - 从 BsonDocument 反序列化为字符串并序列化回 BsonDocument

ios - react-native-firebase notifications().onNotification() 从不在 ios 中调用

c# - 图片在 Chrome 上工作正常,但在 IE 上不行

c# - Xamarin Mac FFmpeg 启动路径无法访问

json - 如何在Groovy中将新的json字段添加到现有的json

javascript - 获取 BehaviorSubject 的值

javascript - 可以在 console.log 中获取多个输出,但不能获取 HTML