C# 操作 JSON

C# 操作 JSON,最常用的是 System.Text.Json ,这是 .NET 自带的 JSON 序列化/反序列化库,不需要额外安装。它主要用来把 C# 对象转 JSON ,或者把 JSON 转 C# 对象 。微软官方文档也推荐通过 JsonSerializer.SerializeJsonSerializer.Deserialize 来完成这些操作。(Microsoft Learn)


一、准备一个类

比如我们有一个设备数据类:

复制代码
public class DeviceData
{
    public string DeviceId { get; set; } = "";
    public double Temperature { get; set; }
    public double Humidity { get; set; }
    public bool Online { get; set; }
}

二、对象转 JSON

复制代码
using System.Text.Json;

DeviceData data = new DeviceData
{
    DeviceId = "D001",
    Temperature = 26.5,
    Humidity = 60.2,
    Online = true
};

string json = JsonSerializer.Serialize(data);

Console.WriteLine(json);

输出结果:

复制代码
{"DeviceId":"D001","Temperature":26.5,"Humidity":60.2,"Online":true}

三、JSON 转对象

复制代码
using System.Text.Json;

string json = """
{
    "DeviceId": "D001",
    "Temperature": 26.5,
    "Humidity": 60.2,
    "Online": true
}
""";

DeviceData? data = JsonSerializer.Deserialize<DeviceData>(json);

if (data != null)
{
    Console.WriteLine(data.DeviceId);
    Console.WriteLine(data.Temperature);
    Console.WriteLine(data.Humidity);
    Console.WriteLine(data.Online);
}

四、格式化输出 JSON

默认生成的 JSON 是压缩的,不方便看。可以加格式化参数:

复制代码
using System.Text.Json;

DeviceData data = new DeviceData
{
    DeviceId = "D001",
    Temperature = 26.5,
    Humidity = 60.2,
    Online = true
};

var options = new JsonSerializerOptions
{
    WriteIndented = true
};

string json = JsonSerializer.Serialize(data, options);

Console.WriteLine(json);

输出:

复制代码
{
  "DeviceId": "D001",
  "Temperature": 26.5,
  "Humidity": 60.2,
  "Online": true
}

五、List 集合转 JSON

实际项目中经常是一组数据:

复制代码
using System.Text.Json;

List<DeviceData> list = new List<DeviceData>
{
    new DeviceData
    {
        DeviceId = "D001",
        Temperature = 26.5,
        Humidity = 60.2,
        Online = true
    },
    new DeviceData
    {
        DeviceId = "D002",
        Temperature = 28.1,
        Humidity = 58.7,
        Online = false
    }
};

string json = JsonSerializer.Serialize(list, new JsonSerializerOptions
{
    WriteIndented = true
});

Console.WriteLine(json);

输出:

复制代码
[
  {
    "DeviceId": "D001",
    "Temperature": 26.5,
    "Humidity": 60.2,
    "Online": true
  },
  {
    "DeviceId": "D002",
    "Temperature": 28.1,
    "Humidity": 58.7,
    "Online": false
  }
]

六、JSON 数组转 List

复制代码
using System.Text.Json;

string json = """
[
  {
    "DeviceId": "D001",
    "Temperature": 26.5,
    "Humidity": 60.2,
    "Online": true
  },
  {
    "DeviceId": "D002",
    "Temperature": 28.1,
    "Humidity": 58.7,
    "Online": false
  }
]
""";

List<DeviceData>? list = JsonSerializer.Deserialize<List<DeviceData>>(json);

if (list != null)
{
    foreach (var item in list)
    {
        Console.WriteLine($"{item.DeviceId} - {item.Temperature} - {item.Online}");
    }
}

七、读写 JSON 文件

1. 写入 JSON 文件

复制代码
using System.Text.Json;

DeviceData data = new DeviceData
{
    DeviceId = "D001",
    Temperature = 26.5,
    Humidity = 60.2,
    Online = true
};

string json = JsonSerializer.Serialize(data, new JsonSerializerOptions
{
    WriteIndented = true
});

File.WriteAllText("device.json", json);

Console.WriteLine("JSON 文件已保存");

2. 读取 JSON 文件

复制代码
using System.Text.Json;

string json = File.ReadAllText("device.json");

DeviceData? data = JsonSerializer.Deserialize<DeviceData>(json);

if (data != null)
{
    Console.WriteLine(data.DeviceId);
    Console.WriteLine(data.Temperature);
}

八、忽略大小写

有时候 JSON 字段是小写:

复制代码
{
  "deviceId": "D001",
  "temperature": 26.5,
  "humidity": 60.2,
  "online": true
}

而 C# 类是大写属性:

复制代码
public class DeviceData
{
    public string DeviceId { get; set; } = "";
    public double Temperature { get; set; }
    public double Humidity { get; set; }
    public bool Online { get; set; }
}

这时可以这样写:

复制代码
var options = new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true
};

DeviceData? data = JsonSerializer.Deserialize<DeviceData>(json, options);

九、指定 JSON 字段名

如果你想让 C# 属性名和 JSON 字段名不一样,可以用 [JsonPropertyName]

复制代码
using System.Text.Json.Serialization;

public class DeviceData
{
    [JsonPropertyName("device_id")]
    public string DeviceId { get; set; } = "";

    [JsonPropertyName("temperature")]
    public double Temperature { get; set; }

    [JsonPropertyName("humidity")]
    public double Humidity { get; set; }

    [JsonPropertyName("online")]
    public bool Online { get; set; }
}

然后序列化:

复制代码
using System.Text.Json;

DeviceData data = new DeviceData
{
    DeviceId = "D001",
    Temperature = 26.5,
    Humidity = 60.2,
    Online = true
};

string json = JsonSerializer.Serialize(data, new JsonSerializerOptions
{
    WriteIndented = true
});

Console.WriteLine(json);

输出:

复制代码
{
  "device_id": "D001",
  "temperature": 26.5,
  "humidity": 60.2,
  "online": true
}

十、读取不固定结构的 JSON

如果 JSON 结构不固定,不想先定义类,可以用 JsonDocument

复制代码
using System.Text.Json;

string json = """
{
    "deviceId": "D001",
    "temperature": 26.5,
    "status": {
        "online": true,
        "alarm": false
    }
}
""";

using JsonDocument doc = JsonDocument.Parse(json);

JsonElement root = doc.RootElement;

string deviceId = root.GetProperty("deviceId").GetString()!;
double temperature = root.GetProperty("temperature").GetDouble();
bool online = root.GetProperty("status").GetProperty("online").GetBoolean();

Console.WriteLine(deviceId);
Console.WriteLine(temperature);
Console.WriteLine(online);

这个适合处理第三方接口返回的数据。


十一、结合 MQTT 使用

如果你前面 MQTT 客户端要发布设备数据,就可以这样:

复制代码
using System.Text.Json;
using MQTTnet;

DeviceData data = new DeviceData
{
    DeviceId = "D001",
    Temperature = 26.5,
    Humidity = 60.2,
    Online = true
};

string json = JsonSerializer.Serialize(data);

var message = new MqttApplicationMessageBuilder()
    .WithTopic("factory/device001/status")
    .WithPayload(json)
    .Build();

await mqttClient.PublishAsync(message);

订阅端收到 JSON 后:

复制代码
mqttClient.ApplicationMessageReceivedAsync += e =>
{
    string json = e.ApplicationMessage.ConvertPayloadToString();

    DeviceData? data = JsonSerializer.Deserialize<DeviceData>(json);

    if (data != null)
    {
        Console.WriteLine($"设备:{data.DeviceId}");
        Console.WriteLine($"温度:{data.Temperature}");
        Console.WriteLine($"湿度:{data.Humidity}");
        Console.WriteLine($"在线:{data.Online}");
    }

    return Task.CompletedTask;
};

十二、完整小例子

复制代码
using System.Text.Json;
using System.Text.Json.Serialization;

public class Program
{
    public static void Main()
    {
        DeviceData data = new DeviceData
        {
            DeviceId = "D001",
            Temperature = 26.5,
            Humidity = 60.2,
            Online = true
        };

        var options = new JsonSerializerOptions
        {
            WriteIndented = true
        };

        string json = JsonSerializer.Serialize(data, options);

        Console.WriteLine("对象转 JSON:");
        Console.WriteLine(json);

        DeviceData? newData = JsonSerializer.Deserialize<DeviceData>(json);

        Console.WriteLine();
        Console.WriteLine("JSON 转对象:");

        if (newData != null)
        {
            Console.WriteLine(newData.DeviceId);
            Console.WriteLine(newData.Temperature);
            Console.WriteLine(newData.Humidity);
            Console.WriteLine(newData.Online);
        }
    }
}

public class DeviceData
{
    public string DeviceId { get; set; } = "";
    public double Temperature { get; set; }
    public double Humidity { get; set; }
    public bool Online { get; set; }
}

十三、什么时候用 Newtonsoft.Json?

现在新项目优先用 System.Text.Json。如果你维护老项目,或者需要一些更灵活的 JSON 功能,也可以用 Newtonsoft.JsonNewtonsoft.Json 也叫 Json.NET,是一个常用的第三方 JSON 框架,需要通过 NuGet 安装。(NuGet)

安装:

复制代码
dotnet add package Newtonsoft.Json

使用:

复制代码
using Newtonsoft.Json;

string json = JsonConvert.SerializeObject(data);

DeviceData? obj = JsonConvert.DeserializeObject<DeviceData>(json);

一般你现在写 C# 程序,记住这两个方法就够了:

复制代码
JsonSerializer.Serialize(对象);
JsonSerializer.Deserialize<类型>(json字符串);