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

ASP.NET MVC中C#类序列化为JSON的实现及EF优化方案问询

问题描述

我在ASP.NET MVC项目中通过VS菜单「编辑>选择性粘贴>将JSON粘贴为类」生成了如下C#类:

public class Rootobject { 
    public string MerchantOrderId { get; set; } 
    public Customer Customer { get; set; } 
    public Payment Payment { get; set; } 
} 
public class Customer { 
    public string Name { get; set; } 
} 
public class Payment { 
    public string Type { get; set; } 
    public bool Authenticate { get; set; } 
    public int Amount { get; set; } 
    public string ReturnUrl { get; set; } 
    public Debitcard DebitCard { get; set; } 
} 
public class Debitcard { 
    public string CardNumber { get; set; } 
    public string Holder { get; set; } 
    public string ExpirationDate { get; set; } 
    public string SecurityCode { get; set; } 
    public string Brand { get; set; } 
}

我希望使用自定义数据,而非直接通过「Rootobject obj = new Rootobject { ... }」的方式实例化对象,在控制器中通过「return Json(MyModel, JsonRequestBehavior.AllowGet);」语句将其序列化为指定格式的JSON。请问该如何构建自定义数据模型实现序列化?是否有借助EF实现的更优方案?

解决方案

嘿,其实你已经拿到了最核心的东西——VS生成的这些类本身就是完美适配目标JSON格式的序列化模型,根本不需要额外重新构建!下面我分两种场景给你讲具体实现方式:

一、手动填充自定义数据并序列化

你觉得直接new Rootobject { ... }不够“自定义”?其实可以把数据填充的逻辑抽离出来,比如放到专门的服务类或者方法里,让代码更整洁,示例如下:

1. 抽离数据填充逻辑

先写一个专门的方法来生成填充好的模型,这里的数据可以从任意来源获取:

private Rootobject BuildCustomPaymentModel()
{
    // 示例:从请求表单、配置或第三方接口获取自定义数据
    string orderId = $"ORD-{DateTime.Now:yyyyMMdd}-{new Random().Next(1000,9999)}";
    string customerName = Request.Form["CustomerName"] ?? "默认用户";
    int paymentAmount = int.Parse(Request.Form["Amount"] ?? "500");

    return new Rootobject
    {
        MerchantOrderId = orderId,
        Customer = new Customer { Name = customerName },
        Payment = new Payment
        {
            Type = "DebitCard",
            Authenticate = true,
            Amount = paymentAmount,
            ReturnUrl = Url.Action("PaymentResult", "Home", null, Request.Url.Scheme),
            DebitCard = new Debitcard
            {
                CardNumber = "4111****1111", // 实际项目注意卡号脱敏
                Holder = customerName,
                ExpirationDate = "12/28",
                SecurityCode = "***",
                Brand = "Visa"
            }
        }
    };
}

2. 在控制器中调用并返回

然后在控制器Action里调用这个方法,直接返回JSON:

public ActionResult GeneratePaymentJson()
{
    var myModel = BuildCustomPaymentModel();
    // ASP.NET MVC 5+ 可省略 JsonRequestBehavior.AllowGet,默认允许GET请求返回JSON
    return Json(myModel);
}

3. 自定义属性映射(可选)

如果想要修改类名/属性名,但又要和目标JSON的键保持一致,可以用Newtonsoft.Json的[JsonProperty]特性(需先安装Newtonsoft.Json NuGet包):

using Newtonsoft.Json;

// 把Rootobject改成更有意义的名字
public class PaymentOrder
{
    // 让属性名OrderId对应JSON里的MerchantOrderId
    [JsonProperty("MerchantOrderId")]
    public string OrderId { get; set; }
    public Customer Customer { get; set; }
    public Payment Payment { get; set; }
}

二、借助EF实现的更优方案(数据来自数据库)

如果你的自定义数据来自数据库,EF可以帮你更高效地获取并转换数据,主要有两种方式:

1. 让EF实体类直接匹配序列化结构

如果数据库表结构和目标JSON结构对应,可以直接定义EF实体类(可用EF反向生成工具从数据库生成):

// EF实体类,对应数据库中的PaymentOrders表
public class PaymentOrderEntity
{
    public int Id { get; set; }
    public string MerchantOrderId { get; set; }
    // 导航属性,关联Customer表
    public virtual CustomerEntity Customer { get; set; }
    // 导航属性,关联Payment表
    public virtual PaymentEntity Payment { get; set; }
}

public class CustomerEntity
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int PaymentOrderId { get; set; }
    public virtual PaymentOrderEntity PaymentOrder { get; set; }
}

// 其他实体类(PaymentEntity、DebitcardEntity)同理,和序列化模型结构对齐

然后在控制器中从EF上下文查询数据,直接返回或者转换:

public ActionResult GetPaymentOrderFromDb(int orderId)
{
    using(var dbContext = new YourDbContext())
    {
        // 关联查询所需的导航属性
        var dbOrder = dbContext.PaymentOrders
            .Include(o => o.Customer)
            .Include(o => o.Payment.DebitCard)
            .FirstOrDefault(o => o.Id == orderId);

        if(dbOrder == null)
        {
            return HttpNotFound();
        }

        // 如果EF实体和序列化模型完全一致,直接返回
        return Json(dbOrder);

        // 如果实体和模型结构有差异,手动转换或者用AutoMapper自动映射
        // var serializedModel = new Rootobject
        // {
        //     MerchantOrderId = dbOrder.MerchantOrderId,
        //     Customer = new Customer { Name = dbOrder.Customer.Name },
        //     // 其他属性转换...
        // };
        // return Json(serializedModel);
    }
}

2. 使用EF投影直接生成序列化模型

不需要查询完整的EF实体,直接通过LINQ投影生成需要的序列化模型,这样可以减少数据库查询的数据量,性能更优:

public ActionResult GetProjectedPaymentOrder(int orderId)
{
    using(var dbContext = new YourDbContext())
    {
        var myModel = dbContext.PaymentOrders
            .Where(o => o.Id == orderId)
            .Select(o => new Rootobject
            {
                MerchantOrderId = o.MerchantOrderId,
                Customer = new Customer { Name = o.Customer.Name },
                Payment = new Payment
                {
                    Type = o.Payment.Type,
                    Authenticate = o.Payment.Authenticate,
                    Amount = o.Payment.Amount,
                    ReturnUrl = o.Payment.ReturnUrl,
                    DebitCard = new Debitcard
                    {
                        CardNumber = o.Payment.DebitCard.CardNumber.Substring(0,4) + "****" + o.Payment.DebitCard.CardNumber.Substring(8),
                        Holder = o.Payment.DebitCard.Holder,
                        ExpirationDate = o.Payment.DebitCard.ExpirationDate,
                        SecurityCode = "***",
                        Brand = o.Payment.DebitCard.Brand
                    }
                }
            })
            .FirstOrDefault();

        return myModel == null ? HttpNotFound() : Json(myModel);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:27:16