首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将JsonSerializerSettings从JsonSerializer复制到新JsonSerializer

将JsonSerializerSettings从JsonSerializer复制到新JsonSerializer
EN

Stack Overflow用户
提问于 2016-07-06 17:39:35
回答 2查看 5.5K关注 0票数 20

有没有办法将设置从JsonSerializer类中取出并在新的JsonSerializer中重新实现?

似乎没有任何方法来做这样的事情。我发现最好的方法是通过反射调用私有方法,ApplySerializerSettings

我正在尝试从WriteJson方法中获取序列化程序,并将其复制到一个新的序列化程序中,对其进行一些调整。具体来说,我想替换ContractResolver

代码语言:javascript
复制
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
EN

回答 2

Stack Overflow用户

发布于 2016-07-06 17:39:35

似乎最好的方法就是把所有的设置复制到一个新的对象中。有很多这样的工具,所以这里有一个很好的扩展方法可以使用(从8.0.3开始)。

代码语言:javascript
复制
public static class JsonSerializerExtensions
{
  public static JsonSerializer DeepCopy(this JsonSerializer serializer)
  {
    var copiedSerializer = new JsonSerializer
    {
      Context = serializer.Context,
      Culture = serializer.Culture,
      ContractResolver = serializer.ContractResolver,
      ConstructorHandling = serializer.ConstructorHandling,
      CheckAdditionalContent = serializer.CheckAdditionalContent,
      DateFormatHandling = serializer.DateFormatHandling,
      DateFormatString = serializer.DateFormatString,
      DateParseHandling = serializer.DateParseHandling,
      DateTimeZoneHandling = serializer.DateTimeZoneHandling,
      DefaultValueHandling = serializer.DefaultValueHandling,
      EqualityComparer = serializer.EqualityComparer,
      FloatFormatHandling = serializer.FloatFormatHandling,
      Formatting = serializer.Formatting,
      FloatParseHandling = serializer.FloatParseHandling,
      MaxDepth = serializer.MaxDepth,
      MetadataPropertyHandling = serializer.MetadataPropertyHandling,
      MissingMemberHandling = serializer.MissingMemberHandling,
      NullValueHandling = serializer.NullValueHandling,
      ObjectCreationHandling = serializer.ObjectCreationHandling,
      PreserveReferencesHandling = serializer.PreserveReferencesHandling,
      ReferenceResolver = serializer.ReferenceResolver,
      ReferenceLoopHandling = serializer.ReferenceLoopHandling,
      StringEscapeHandling = serializer.StringEscapeHandling,
      TraceWriter = serializer.TraceWriter,
      TypeNameHandling = serializer.TypeNameHandling,
      SerializationBinder = serializer.SerializationBinder,
      TypeNameAssemblyFormatHandling = serializer.TypeNameAssemblyFormatHandling
    };
    foreach (var converter in serializer.Converters)
    {
      copiedSerializer.Converters.Add(converter);
    }
    return copiedSerializer;
  }
}

它很难看,但至少你只需要写一次。要稍微小心,因为属性本身并不是很深的复制。

下面的答案是片状的,取决于您的实现,特别是在解决契约时。留着以防它对别人有帮助。

所以,我不能完全复制设置,但我发现了一个很好的工作,可能需要考虑。您可以简单地在锁定的上下文中设置要更改的属性,然后在之后重置它们。

代码语言:javascript
复制
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
    var thing = value as IThing;

    if (thing == null)
        throw new ArgumentException($"Writing Json failed because " + 
          "value was not a 'Thing' of type, {typeof(IThing).FullName}");

    JObject jsonThing;
    //If your solution is multithreaded,
    //and is using a shared serializer (which you probably are),
    //you should lock the serializer so that it doesn't accidentally use 
    //the "CustomObjectResolver"
    lock (serializer)
    {
        //Hold the original value(s) to reset later
        var originalContractResolver = serializer.ContractResolver;
        //Set custom value(s)
        serializer.ContractResolver = new CustomObjectResolver();
        //Serialization with custom properties
        jsonThing = JObject.FromObject(value, serializer);
        //Reset original value(s)
        serializer.ContractResolver = originalContractResolver;
    }

    //Finish serializing and write to writer.
}
票数 14
EN

Stack Overflow用户

发布于 2018-10-08 19:11:03

不确定这是否是主题,但由于这是在我的谷歌搜索克隆JSONSerializerSettings时出现的第一条帖子,我想我会留下一个通知。

我刚才也有一个类似的要求。

在我的.Net核心WebApi解决方案中,我们使用默认的方法来序列化JSON

代码语言:javascript
复制
jsonSerializaerSettings.NullValueHandling = NullValueHandling.Ignore;

但是在几个端点中,我也想序列化空属性,因为这些端点代表一个数据集。因此,在序列化时,所有对象都应该具有所有属性。

我尝试了几种方法,然后阅读了选项模式,偶然发现了IOptionSnapshot - https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-2.1#reload-configuration-data-with-ioptionssnapshot

因此,我最终将一个IOptionsSnapshot注入到我的控制器方法中,这给了我一个默认选项的副本,我可以对这个请求进行修改和使用。

在下一个请求中,注入的选项将恢复为默认选项。

很好,很容易-至少是为了我的目的。

所以我的样本的最后一个解决方案是这样的

代码语言:javascript
复制
[HttpPost("dataset", Name = "GetReportDataset")]
public IActionResult GetReportDataset(
    [FromServices]IOptionsSnapshot<MvcJsonOptions> jsonOptions,
    [FromBody]DataSetReport report,
    [FromQuery]int? top)
{
    //Logic to fetch dataset
    var myDataSet = myRepository.GetDataset(report, top);

    var serializerSettings = jsonOptions.Value.SerializerSettings;
    serializerSettings.NullValueHandling = NullValueHandling.Include;

    return new JsonResult(myDataSet, serializerSettings);
}

希望这能帮助其他人来这里进行类似的使用。

/Anders

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38230326

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档