c# - 使用 Json.NET 将嵌套的 Firebase 数据库对象转换为 C# 对象
问题描述
我需要使用 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?
我尝试了几个使用 JObject 循环的递归过程,但没有成功。
提前致谢!
解决方案
您可以将 JSON 反序列化为 a 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();
}
}
}
但正如您所见,解决方案开始变得有些复杂。除非您需要为许多类型执行此操作,否则手动转换可能会更省时且更易于维护。
推荐阅读
- php - 如何将php正则表达式输出与switch函数中的字符串进行比较?
- asp.net-mvc - Asp.Net MVC 如何发送更新的模型来查看?
- node.js - Node JS Express 调用多个 API 并返回单个响应
- php - PHP fputcsv 上的换行符
- ibm-watson - 在 Watson Assistant 中重用实体会导致自动填充上下文变量
- terraform - 排除 terraform 模块源中的文件
- html - 我应该给 div 一个非常具体的类名,然后用类选择器或非常通用的名称选择它,然后用后代选择器选择它
- haskell - 类型构造函数可以与值构造函数相同吗?
- java - 尝试将应用程序部署到本地 Tomcat 服务器时出错
- java - 使用 Hibernate Provider 的 JUnit 测试 JPA (java.lang.NoSuchMethodError: javax.persistence.spi.PersistenceUnitInfo...)