131 lines
4.9 KiB
C#
131 lines
4.9 KiB
C#
using System.IO;
|
|
using System.Text.Json;
|
|
using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Linq;
|
|
using JsonSerializer = System.Text.Json.JsonSerializer;
|
|
using Xunit;
|
|
using Yh.Platform.Abstractions;
|
|
|
|
namespace Yh.Platform.Abstractions.Tests;
|
|
|
|
public class ModelSerializationTests
|
|
{
|
|
private static JObject LoadFixtureBareData()
|
|
{
|
|
var path = Path.Combine(AppContext.BaseDirectory, "fixtures", "envelope-success.json");
|
|
return JObject.Parse(File.ReadAllText(path))["bareData"]!.Value<JObject>()!;
|
|
}
|
|
|
|
private static JObject LoadFixtureWrapped()
|
|
{
|
|
var path = Path.Combine(AppContext.BaseDirectory, "fixtures", "envelope-success.json");
|
|
return JObject.Parse(File.ReadAllText(path))["wrappedData"]!.Value<JObject>()!;
|
|
}
|
|
|
|
[Fact]
|
|
public void Newtonsoft_反序列化fixture_含currentRole嵌套()
|
|
{
|
|
var user = LoadFixtureBareData().ToObject<BoaUser>(new Newtonsoft.Json.JsonSerializer
|
|
{
|
|
// net5 消费方形态:ASP.NET Core AddNewtonsoftJson 默认大小写不敏感、保留属性名
|
|
ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(),
|
|
});
|
|
|
|
Assert.Equal(1001, user!.Id);
|
|
Assert.Equal("zhangsan", user.Account);
|
|
Assert.Equal("张三", user.Name);
|
|
Assert.Equal(2, user.School!.Id);
|
|
Assert.Equal("云海第一中学", user.School.Name);
|
|
Assert.Equal(3, user.CurrentRole!.RoleId);
|
|
Assert.Equal("教师", user.CurrentRole.RoleName);
|
|
Assert.Equal("云海第一中学", user.CurrentRole.SchName);
|
|
Assert.Equal(21, user.CurrentRole.ChildId);
|
|
Assert.Equal(2, user.Schools!.Count);
|
|
Assert.Equal(new List<int> { 3, 5 }, user.RoleIds);
|
|
Assert.Equal(3, user.Groups!.Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void Newtonsoft_默认设置_大小写不敏感匹配camelCase()
|
|
{
|
|
var user = LoadFixtureBareData().ToObject<BoaUser>();
|
|
Assert.Equal("zhangsan", user!.Account);
|
|
Assert.Equal("教师", user.CurrentRole!.RoleName);
|
|
}
|
|
|
|
[Fact]
|
|
public void SystemTextJson_Web序列化_与fixture逐节点一致()
|
|
{
|
|
var user = LoadFixtureBareData().ToObject<BoaUser>();
|
|
var options = new JsonSerializerOptions(JsonSerializerDefaults.Web)
|
|
{
|
|
// 对齐 Java 侧 NON_NULL 语义
|
|
DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull,
|
|
};
|
|
var json = JsonSerializer.Serialize(user, options);
|
|
|
|
// 语义等价:键序无关、null 节点差异容忍(fixture 中显式 null 与省略 null 视为一致)
|
|
Assert.True(JToken.DeepEquals(JObject.Parse(json), StripNulls(LoadFixtureBareData())),
|
|
"STJ 序列化结果应与 fixture 语义一致\n" + json);
|
|
}
|
|
|
|
private static JObject StripNulls(JObject obj)
|
|
{
|
|
var clone = (JObject)obj.DeepClone();
|
|
var toRemove = new List<JProperty>();
|
|
CollectNullProps(clone, toRemove);
|
|
foreach (var p in toRemove)
|
|
{
|
|
p.Remove();
|
|
}
|
|
return clone;
|
|
}
|
|
|
|
private static void CollectNullProps(JToken token, List<JProperty> collected)
|
|
{
|
|
foreach (var child in token.Children())
|
|
{
|
|
if (child is JProperty p)
|
|
{
|
|
if (p.Value.Type == JTokenType.Null)
|
|
{
|
|
collected.Add(p);
|
|
continue;
|
|
}
|
|
CollectNullProps(p.Value, collected);
|
|
}
|
|
else if (child.Type is JTokenType.Object or JTokenType.Array)
|
|
{
|
|
CollectNullProps(child, collected);
|
|
}
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void SystemTextJson_反序列化信封包裹成功样例()
|
|
{
|
|
var wrapped = LoadFixtureWrapped();
|
|
var envelope = wrapped.ToObject<ApiEnvelope<BoaUser>>(new Newtonsoft.Json.JsonSerializer
|
|
{
|
|
ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(),
|
|
});
|
|
|
|
Assert.True(envelope!.IsSuccess);
|
|
Assert.Equal(0, envelope.Code);
|
|
Assert.Equal(1001, envelope.Data!.Id);
|
|
}
|
|
|
|
[Fact]
|
|
public void BoaApp_Models_双序列化往返()
|
|
{
|
|
var app = new BoaApp { Id = 7, Name = "作业提交", Clients = (int)ClientEnum.PcBrowser | (int)ClientEnum.MobileApp, IsPublic = false, BuiltInTag = 0 };
|
|
var stj = JsonSerializer.Deserialize<BoaApp>(JsonSerializer.Serialize(app, new JsonSerializerOptions(JsonSerializerDefaults.Web)), new JsonSerializerOptions(JsonSerializerDefaults.Web));
|
|
var nf = JObject.Parse(JsonConvert.SerializeObject(app, new JsonSerializerSettings { ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver() })).ToObject<BoaApp>();
|
|
|
|
Assert.Equal(app.Name, stj!.Name);
|
|
Assert.Equal(app.Clients, stj.Clients);
|
|
Assert.Equal(app.Name, nf!.Name);
|
|
Assert.Equal(false, nf.IsPublic);
|
|
}
|
|
}
|