C# 填充字典值

C# populate dictionary value

我是 C# 的新手,我遇到了一个我无法解决的问题。

我听我的小米网关获取信息。这些信息有两种类型,报告或心跳。

报告是什么时候触发传感器,对于插头,当你打开或关闭它时:

{"cmd":"report","model":"plug","sid":"158d000123f0c9","short_id":11119,"data":"{\"status\":\"off\"}"}

心跳每 x 分钟发送一次,表示传感器仍然存在:

{"cmd":"heartbeat","model":"plug","sid":"158d000123f0c9","short_id":11119,"data":"{\"voltage\":3600,\"status\":\"on\",\"inuse\":\"0\",\"power_consumed\":\"48\",\"load_power\":\"0.00\"}"}

如您所见,报告和心跳不包含与数据相同的参数。

这是我的插件 class :

[XiaomiEquipement("plug")]
public class Plug
{
    public string Model { get; set; } = "plug";
    public string Sid { get; set; }
    public string Battery { get; set; } = "CR2450";
    public int BatteryLevel { get; set; }
    public PlugReport Report { get; set; }
}

[XiaomiEquipement("plug_report")]
public class PlugReport
{
    public int Voltage { get; set; }
    public string Status { get; set; }
    public int InUse { get; set; }
    public float Power_Consume { get; set; }
    public float Load_Power { get; set; }
}

好的,当我启动我的应用程序时,我向网关询问所有传感器并将它们输入到双字典中:

dynamic Equipements = new Dictionary<string, Dictionary<string, dynamic>>();

当我收到报告或心跳时,我搜索字典条目,修改它并发送到我的家庭自动化系统:

Type modelReportType = Assembly.GetExecutingAssembly().GetTypes().SingleOrDefault(t => t.GetCustomAttribute<Response.XiaomiEquipementAttribute>()?.Model == data.Model + "_report");
dynamic test = Equipements[data.Model][data.Sid].Report;
dynamic data = JsonConvert.DeserializeObject(Convert.ToString(data.Data), modelReportType);

如果数据不包含所有 属性,它会默认写入它们。

我想要的是,如果 属性 在 report/heartbeat 上不存在,则使用字典值。

例如,我的字典包含:

{"model":"plug","sid":"158d000123f0c9","short_id":11119,"data":"{\"voltage\":3600,\"status\":\"on\",\"inuse\":\"1\",\"power_consumed\":\"48\",\"load_power\":\"3.56\"}"}

我收到了:

{"cmd":"report","model":"plug","sid":"158d000123f0c9","short_id":11119,"data":"{\"status\":\"off\"}"}

我要:

{"model":"plug","sid":"158d000123f0c9","short_id":11119,"data":"{\"voltage\":3600,\"status\":\"off\",\"inuse\":\"1\",\"power_consumed\":\"48\",\"load_power\":\"3.56\"}"}

我暂时得到:

{"model":"plug","sid":"158d000123f0c9","short_id":11119,"data":"{\"voltage\":3600,\"status\":\"off\",\"inuse\":\"0\",\"power_consumed\":\"00\",\"load_power\":\"0.00\"}"}

我试过 PopulateObject 但它没有用:

dynamic data = JsonConvert.PopulateObject(Convert.ToString(data.Data), test);

有人想在不影响其他属性的情况下修改我的动态变量吗?

编辑:一些报告示例:

> {"cmd":"report","model":"weather.v1","sid":"158d0001a231ab","short_id":39499,"data":" {\"humidity\":\"5262\"}"}

{"cmd":"report","model":"magnet","sid":"158d000159febe","short_id":40805,"data":"{\"status\":\"close\"}"}

对于心跳:

{"cmd":"heartbeat","model":"sensor_ht","sid":"158d0001a2c3e9","short_id":42820,"data":"{\"voltage\":3015,\"temperature\":\"2644\",\"humidity\":\"5454\"}"} {"cmd":"heartbeat","model":"magnet","sid":"158d000159febe","short_id":40805,"data":"{\"voltage\":3025,\"status\":\"open\"}"}

正如我所说,我事先并不知道传感器是什么,所以一切都必须在任何情况下都能正常工作。

这就是为什么当我收到 report/heartbeat 时,我根据模型名称搜索报告 class,将数据部分反序列化为此 class 的实例。

至于我,你不应该使用动态。而不是这个,尝试类似的东西。

public class Data
{
    [JsonProperty("status")]
    public string Status { get; set; }
}

public class ReportResponse
{
    [JsonProperty("cmd")]
    public string Cmd { get; set; }
    [JsonProperty("model")]
    public string Model { get; set; }
    [JsonProperty("sid")]
    public string Sid { get; set; }
    [JsonProperty("short_id")]
    public int Short_id { get; set; }

    [JsonProperty("data")]
    public Dictionary<string, string> Data { get; set; }
    //public Data Data { get; set; }
}

var deserializeReponse = JsonConvert.DeserializeObject<ReportResponse>(rawResponse);

当您以这种风格编写时,您的代码会更清晰,您得到的异常也会更容易理解

P.S.

当我需要从 json 生成对象时,我使用这两个站点:

Getting formatted json

POCO generator