我想用一些元数据将一些属性包装在 JSON 对象中,无论它是否为空。但是,JsonConverter.WriteJson如果属性为 ,则不会调用我的自定义覆盖null。
当属性不为空时我得到什么:
{"Prop":{"Version":1, "Object":{"Content":"abc"}}}
Run Code Online (Sandbox Code Playgroud)
当它为空时我得到什么:
{"Prop":null}
Run Code Online (Sandbox Code Playgroud)
当它为空时我想要什么:
{"Prop":{"Version":1, "Object":null}}
Run Code Online (Sandbox Code Playgroud)
由于WriteJson从未被要求提供空值,我没有机会控制这种行为。有什么办法可以强制这样做吗?
请注意,我想知道这是否可以与转换器或合约解析器等一起使用,我不能/不想更改MyContent或Wrap类(见下文)。
class VersioningJsonConverter : JsonConverter
{
//Does not get called if value is null !!
public override void WriteJson(JsonWriter writer, Object value, JsonSerializer serializer)
{
writer.WriteStartObject();
writer.WritePropertyName("v");
writer.WriteValue(1);
writer.WritePropertyName("o");
if(value == null)
{
//never happens
writer.WriteNull();
}
else
{
writer.WriteStartObject();
writer.WritePropertyName("Content");
writer.WriteValue((value as MyContent).Content);
writer.WriteEndObject();
}
writer.WriteEndObject();
}
public override Object ReadJson(JsonReader reader, Type objectType, …Run Code Online (Sandbox Code Playgroud) 我正在对我的班级财产的驼峰式外壳使用以下设置。
JsonSerializerSettings settings = new JsonSerializerSettings()
{
ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
};
Run Code Online (Sandbox Code Playgroud)
对象中的某些属性属于其他类类型。我不想更改这些属性的大小写。
例如:
Public Class CaseToChange
{
public string StringProperty{get;set;} //Change to camelCase
public SomeOtherType OtherTypeProperty{get;set;} //Change name of this to camelCase but not property name of "SomeOtherType"
}
Run Code Online (Sandbox Code Playgroud)
如何使用 JsonSerializerSettings 实现这一点?
我使用TypeNameHandling在json中序列化和反序列化派生类的列表.它与属性和属性完美配合JsonProperty
public abstract class Animal
{
public bool CanFly { get; set;}
}
public class FlyingAnimal : Animal
{
public FlyingAnimal() { this.CanFly = true; }
}
public class SwimmingAnimal : Animal
{
public SwimmingAnimal() { this.CanFly = false; }
}
public class World
{
public World() {
this.Animals = new List<Animal>();
this.Animals.Add(new FlyingAnimal());
this.Animals.Add(new SwimmingAnimal());
}
[JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto)]
public List<Animal> Animals { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
现在,我需要一个返回派生类列表的WebAPI:
[RoutePrefix("Animals")]
public class AnimalsController : ApiController
{
public …Run Code Online (Sandbox Code Playgroud) 我需要将小数的输出json格式化为货币,并在要序列化的对象中指定文化,对象可以嵌套,因此无法在序列化器中预设选项。我当前的操作方式是使用额外的字符串属性来格式化输出。
[JsonIgnore]
public decimal Cost {get;set;}
[JsonIgnore]
public CultureInfo Culture {get;set;}
public string AsCurrency(decimal value) {
return string.Format(this.Culture, "{0:c}", value);
}
[JsonProperty("FormattedCost")]
public string FormatedCost {
get { return this.AsCurrency(this.Cost); }
}
Run Code Online (Sandbox Code Playgroud)
我有很多要处理的属性,我不介意反序列化,另一种语言使用JsonObject填充PDF,所以我想要字符串值。
理想情况下,我想要一个,JsonConverter所以我可以做
[JsonProperty("FormattedCost")]
[JsonConverter(typeof(MyCurrencyConverter))]
public decimal Cost {get;set;}
Run Code Online (Sandbox Code Playgroud)
我的问题是如何访问转换器中包含对象的Culture属性。
public class MyCurrencyConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var culture = // How do I get the Culture from the parent object?
writer.WriteValue(string.format(culture, "{0:c}", (decimal)value);
}
public override object …Run Code Online (Sandbox Code Playgroud) 在我的项目中,我编写了一个自定义 json 转换器来修剪 string 属性中存在的空格。
这是我们将使用的典型类的示例,
public class Candidate
{
public string CandidateName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这是我的自定义 json 转换器
public class StringSanitizingConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(string);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue , JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.String)
if (reader.Value != null)
{
string sanitizedString = (reader.Value as string).Trim();
if (StringSanitizeOptions.HasFlag(StringSanitizeOptions.ToLowerCase))
sanitizedString = sanitizedString.ToLowerInvariant();
return sanitizedString;
}
return reader.Value;
}
public override void …Run Code Online (Sandbox Code Playgroud) 我有一个带有控制器的 ASP.NET Core 2.2 项目,其 GET 方法返回一个包含System.IO.FileInfo属性的对象。当我调用 API 时(例如在 Web 浏览器中),它返回一个不完整的 JSON 字符串。
这是实例正在序列化的类:
public class Thing
{
public string Name { get; set; }
public FileInfo File { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这是控制器、程序和启动类:
[Route("Test/Home")]
[ApiController]
public class HomeController : Controller
{
[HttpGet]
public async Task<ActionResult<Thing>> GetThing()
{
return new Thing()
{
Name = "First thing",
File = new FileInfo("c:\file.txt")
};
}
}
public class Program
{
public static async Task Main(string[] args)
=> await CreateWebHostBuilder(args).Build().RunAsync();
public static …Run Code Online (Sandbox Code Playgroud) 在对非常高吞吐量的应用程序进行性能测试期间,我们发现 JSON.NET 的ContractResolver. 不幸的是,当您指定一个时ContractResolver,性能似乎变得难以忍受,包括DefaultContractResolver
寻求其他专家的建议,以获取有关如何获得性能而不锁定 CPU 并占用不合理时间的任何建议。现在,由于这个问题,我们看到性能下降了 87%(有任何ContractResolver定义的每秒 80 个请求,没有ContractResolver
定义的每秒 600 个请求。
测试运行的输出是:
默认解析器: Time elapsed 3736 milliseconds
NoOp 解析器: Time elapsed 4150 milliseconds
无解析器: Time elapsed 8 milliseconds
蛇盒: Time elapsed 4753 milliseconds
第三方(SnakeCase.JsonNet): Time elapsed 3881 milliseconds
突出这一点的测试如下:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using SnakeCase.JsonNet;
namespace Anonymous.Public.Namespace
{
public class Person
{
public string Name { get; set; }
public DateTime DateOfBirth …Run Code Online (Sandbox Code Playgroud) 我遇到了一个问题,我创建的ASP.NET MVC html帮助器方法每次调用时都不会被"重新生成".
辅助方法的目的是创建要在angularjs框架中使用的Javascript对象.例如,这是一个代码片段,其中使用了helper方法(从html页面的脚本标记内调用):
var app = angular.module( "appName", ["ui.bootstrap"] );
app.controller( 'appCtrl', function( $scope ) {
$scope.model = @Html.ToJavascript( Model, new string[] { "FirstName", "LastName", "ID", "Role" } );
} );
Run Code Online (Sandbox Code Playgroud)
Model是一个具有各种属性的类的实例,但我只希望将FirstName,LastName,ID和Role序列化为javascript对象.
ToJavascript()帮助器方法在statis类中定义如下:
public static HtmlString ToJavascript( this HtmlHelper helper, object toConvert, string[] includedFields = null, Formatting formatting = Formatting.Indented, ReferenceLoopHandling loopHandling = ReferenceLoopHandling.Ignore )
{
using( var stringWriter = new StringWriter() )
using( var jsonWriter = new JsonTextWriter( stringWriter ) )
{
var serializer = new JsonSerializer()
{ …Run Code Online (Sandbox Code Playgroud) 我有一个看起来像这样的自定义类:
public class PartnerLoginOptions
{
public string Username { get; set; }
public string Password { get; set; }
public string DeviceModel { get; set; }
public string Version { get; set; }
public bool? IncludeUrls { get; set; }
public bool? ReturnDeviceType { get; set; }
public bool? ReturnUpdatePromptVersions { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我想bool?在序列化时忽略任何具有默认值的成员,但保留具有空值的字符串。例如,如果我有一个这样的对象
var options = new PartnerLoginOptions
{
Username = null,
Password = "123",
IncludeUrls = null,
ReturnDeviceType = true
};
Run Code Online (Sandbox Code Playgroud)
然后序列化将导致:
{
"username": …Run Code Online (Sandbox Code Playgroud) 我有一个包含许多数据合同的系统,其成员用以下内容进行装饰:
[DataMember(EmitDefaultValue = false)]
Run Code Online (Sandbox Code Playgroud)
我有一个案例,当序列化为JSON时,我需要在null时包含成员.无论我选择哪种串行器设置,我都无法使用它.
[TestMethod]
public void SerializationTest()
{
var contract = Activator.CreateInstance(typeof(TestContract));
var formatter = new JsonMediaTypeFormatter
{
SerializerSettings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Include,
DefaultValueHandling = DefaultValueHandling.Ignore,
TypeNameHandling = TypeNameHandling.All,
ContractResolver = new DataContractResolver(),
Binder = new DataContractBinder()
}
};
var result = JsonConvert.SerializeObject(contract, formatter.SerializerSettings);
}
Run Code Online (Sandbox Code Playgroud)
我甚至创建了一个自定义数据合约解析器,它为每个属性提供了额外的覆盖.
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, MemberSerialization.Fields);
property.NullValueHandling = NullValueHandling.Include;
property.DefaultValueHandling = DefaultValueHandling.Ignore;
property.ShouldSerialize = o => true;
return property;
}
Run Code Online (Sandbox Code Playgroud)
我已经尝试了空值处理和默认值处理的所有变体来忽略emit默认值= false.根据json …
[Table("LegalEntity")]
[ModelMetadataType(typeof(LegalEntityMeta))]
public class LegalEntity : Entity<long>
{
}
public class LegalEntityMeta
{
[JsonProperty(PropertyName = "LegalEntityId")]
public long Id { get; set; }
[JsonProperty(PropertyName = "LegalEntityName")]
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
在Startup.cs中...
services
.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
})
.AddAutoMapper(typeof(Startup))
.AddMvcCore()
.AddJsonFormatters()
.AddApiExplorer();
Run Code Online (Sandbox Code Playgroud)
我的期望是看到具有属性legalEntityId和legalEntityName的json,但生成的json具有id和name作为属性。有人可以帮助我如何更改json属性吗?谢谢阿南德
我希望能够使用CamelCasePropertyNameContractResolver但覆盖特定的属性名称.为此,我使用该JsonProperty属性.这种方法很好,除非我选择的名称是完全大写的.任何想法有什么问题或如何解决它?
在下面的示例中,Bar序列化为"BAR"当我不使用CamelCasePropertyNameContractResolver时,但"bar"在我使用解析器时被序列化.Foo并CamelCaseProperty在两种情况下都能正确序列化.
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace ConsoleTester
{
class Program
{
static void Main(string[] args)
{
var foo = new FooBar {CamelCaseProperty = "test", Foo = "test", Bar = "test" };
var output = JsonConvert.SerializeObject(foo);
// output "CamelCaseProperty", "fOO", "BAR"
var output2 = JsonConvert.SerializeObject(foo, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() });
// output "camelCaseProperty", "fOO", "bar"
}
}
public class FooBar
{
public string …Run Code Online (Sandbox Code Playgroud)