You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义对象序列化含Null属性,无法生成合规API请求体的问题

问题描述

我用下面的C#代码给API端点发送请求:

public static async Task PostPosition(string authorizationHeader, string apiUrl, string subDirectory, string xRoutingToken, string xApiKey, CustomObject payload)
{
    using (HttpClient client = new HttpClient())
    {
        // 设置请求头
        client.DefaultRequestHeaders.Add("Accept", "application/json, text/plain");
        client.DefaultRequestHeaders.Add("Authorization", authorizationHeader);
        client.DefaultRequestHeaders.Add("x-api-key", xApiKey);
        client.DefaultRequestHeaders.Add("x-routing-token", xRoutingToken);

        Console.WriteLine(apiUrl+subDirectory);

        
        string jsonPayload = System.Text.Json.JsonSerializer.Serialize(payload);
        var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");

        try
        {
            HttpResponseMessage response2 = await client.PostAsync(apiUrl + subDirectory, content);
            Console.WriteLine($"响应状态码: {response2.StatusCode}");
            Console.WriteLine($"响应内容: {await response2.Content.ReadAsStringAsync()}");
        }
        catch
        {
            Console.WriteLine("位置信息发送失败");
        }
    }
}

当前遇到的问题是:发送包含null属性的CustomObject时,序列化后的JSON会包含所有属性(未赋值的属性值为null),但目标API仅需要部分字段。我的CustomObject类定义及构造器如下:

namespace Project
{
    // 定义两个构造器:一个初始化所有字段,一个初始化实际要用的字段
    public class CustomObject
    {
        public string id { get; set; }
        public string? unit_address { get; set; }
        public string? position_date { get; set; }
        public double? latitude { get; set; }
        public double? longitude { get; set; }
        public string? position_status { get; set; }
        public string? position_type { get; set; }
        public bool? ignition { get; set; }
        public int? speed { get; set; }
        public string? direction { get; set; }
        public long? odometer { get; set; }

        // 初始化所有属性的构造器
        public CustomObject(string objectId,
        string unitAddress,
        string positionDate,
        double lat,
        double lon,
        string posStatus,
        string posType,
        bool ign,
        int spd,
        string dir,
        long odom)
        {
            id = objectId;
            unit_address = unitAddress;
            position_date = positionDate;
            latitude = lat;
            longitude = lon;
            position_status = posStatus;
            position_type = posType;
            ignition = ign;
            speed = spd;
            direction = dir;
            odometer = odom;
        }
        // 仅初始化实际所需字段的构造器
        public CustomObject(string iid, double llatitude, double llongitude, string ppositionDate)
        {
            this.id = iid;
            this.latitude = llatitude;
            this.longitude = llongitude;
            this.position_date = ppositionDate;
        }
    }
}

目标API只需要id、position_date、latitude、longitude这几个字段。使用匿名对象(如下)可以成功完成请求:

var payload2 = new
{
    id = "IDNUMBERHERE",
    position_date = "20230101010000-0400",
    latitude = 35.542887,
    longitude = -79.778473,
};

但用CustomObject的构造器创建实例时:

CustomObject payload3 = new CustomObject("IDHere", 35.542887, -79.778473, "20230101010000-0400");

序列化后的JSON会包含所有属性,未赋值的属性值为null:

{
  "id": "IDHere",
  "unit_address": null,
  "position_date": "20230101010000-0400",
  "latitude": 35.542887,
  "longitude": -79.778473,
  "position_status": null,
  "position_type": null,
  "ignition": null,
  "speed": null,
  "direction": null,
  "odometer": null
}

我需要序列化后的JSON仅包含有值的属性,如下所示:

{
  "id": "IDHere",
  "position_date": "20230101010000-0400",
  "latitude": 35.542887,
  "longitude": -79.778473
}

请问如何修改构造器、类或序列化配置来实现这一需求?


解决方案

方法1:修改序列化配置(推荐,无需改动类结构)

直接给System.Text.Json的序列化器添加忽略null值属性的配置,修改序列化代码即可:

var options = new JsonSerializerOptions
{
    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
};
string jsonPayload = System.Text.Json.JsonSerializer.Serialize(payload, options);

这样序列化时,所有值为null的属性会被自动忽略,完全符合需求。

方法2:给不需要的属性添加[JsonIgnore]特性

如果确定某些字段永远不需要传给API,可以直接在类的对应属性上标记[JsonIgnore]特性:

namespace Project
{
    public class CustomObject
    {
        public string id { get; set; }
        [JsonIgnore]
        public string? unit_address { get; set; }
        public string? position_date { get; set; }
        public double? latitude { get; set; }
        public double? longitude { get; set; }
        [JsonIgnore]
        public string? position_status { get; set; }
        [JsonIgnore]
        public string? position_type { get; set; }
        [JsonIgnore]
        public bool? ignition { get; set; }
        [JsonIgnore]
        public int? speed { get; set; }
        [JsonIgnore]
        public string? direction { get; set; }
        [JsonIgnore]
        public long? odometer { get; set; }

        // 构造器代码保持不变
        // ...
    }
}

这种方法适合字段固定不需要发送的场景,但如果后续需要发送某些字段,需重新修改类定义。

方法3:拆分类结构

创建一个专门用于API请求的精简类,只包含需要的字段:

public class PositionApiRequest
{
    public string id { get; set; }
    public string position_date { get; set; }
    public double latitude { get; set; }
    public double longitude { get; set; }

    public PositionApiRequest(string id, string positionDate, double latitude, double longitude)
    {
        this.id = id;
        this.position_date = positionDate;
        this.latitude = latitude;
        this.longitude = longitude;
    }
}

然后将PostPosition方法的参数类型改为PositionApiRequest,这样序列化时自然只会包含目标字段,也避免了原类冗余属性的干扰。

内容的提问来源于stack exchange,提问作者dylatwork

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 23:17:31