Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何以与Json.NET对象相同的方式序列化JObject?_C#_Json.net - Fatal编程技术网

C# 如何以与Json.NET对象相同的方式序列化JObject?

C# 如何以与Json.NET对象相同的方式序列化JObject?,c#,json.net,C#,Json.net,如何控制JObject到字符串的序列化 我有一些返回JObject的API,我通常会应用一些更改并保存或返回它们。我希望避免保留空属性并应用一些额外的格式,但JsonConvert似乎完全忽略了我的设置 以下是问题的示例: // startup.cs has the following services.AddMvc().AddJsonOptions(o => { o.SerializerSettings.NullValueHandling = NullValueHandling.

如何控制JObject到字符串的序列化

我有一些返回JObject的API,我通常会应用一些更改并保存或返回它们。我希望避免保留空属性并应用一些额外的格式,但JsonConvert似乎完全忽略了我的设置

以下是问题的示例:

// startup.cs has the following
services.AddMvc().AddJsonOptions(o =>
{
    o.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
});

public class SampleController : Controller
{
    JsonSerializerSettings _settings = new JsonSerializerSettings
    {
        NullValueHandling = NullValueHandling.Ignore
    };

    [HttpPost]
    [Route("object")]
    public object PostObject([FromBody] SomeObject data)
    {
        return JsonConvert.SerializeObject(data, _settings);
    }

    [HttpPost]
    [Route("jobject")]
    public object PostJObject([FromBody] JObject data)
    {
        return JsonConvert.SerializeObject(data, _settings);
    }

    public class SomeObject
    {
        public string Foo { get; set; }
        public string Bar { get; set; }
    }
}
发布
{“Foo”:“Foo”,“Bar”:null}

  • /object
    返回
    {“Foo”:“Foo”}
  • /jobject
    返回
    {“Foo”:“Foo”,“Bar”:null}

我希望JObject方法返回与使用对象相同的输出json。如何在不创建助手的情况下实现这一点?是否有方法使用相同的设置序列化JObject?

当序列化
JObject
时,会写入原始JSON
JsonSerializerSettings
不会影响其编写的JSON。

我能够做到这一点的唯一方法是首先将
JObject
转换为
string
,然后将该字符串反序列化为
ExpandoObject
(不要反序列化为
object
,因为你会得到
JObject
)。
ExpandoObject
就像一个字典,它将导致
JsonConvert
实际调用配置的名称大小写策略。我不确定Newtonsoft.Json的作者为什么没有像处理字典类型那样处理JObject类型,但至少这项工作是可行的

例如:

// Construct a JObject.
var jObject = JObject.Parse("{ SomeName: \"Some value\" }");

// Deserialize the object into an ExpandoObject (don't use object, because you will get a JObject).
var payload = JsonConvert.DeserializeObject<ExpandoObject>(jObject.ToString());

// Now you can serialize the object using any serializer settings you like.
var json = JsonConvert.SerializeObject(payload, new JsonSerializerSettings
{
    ContractResolver = new DefaultContractResolver
    {
        NamingStrategy = new CamelCaseNamingStrategy
        {
            // Important! Make sure to set this to true, since an ExpandoObject is like a dictionary.
            ProcessDictionaryKeys = true,
        }
    }
}
);

Console.WriteLine(json); // Outputs: {"someName":"Some value"}
//构造一个作业对象。
var jObject=jObject.Parse(“{SomeName:\“Some value\”}”);
//将对象反序列化为ExpandooObject(不要使用object,因为这样会得到一个JobObject)。
var payload=JsonConvert.DeserializeObject(jObject.ToString());
//现在,您可以使用喜欢的任何序列化程序设置序列化对象。
var json=JsonConvert.SerializeObject(有效负载,新的JsonSerializerSettings
{
ContractResolver=新的DefaultContractResolver
{
NamingStrategy=新CamelCaseNamingStrategy
{
//重要提示!请确保将其设置为true,因为ExpandoObject就像一本字典。
ProcessDictionaryKeys=true,
}
}
}
);
Console.WriteLine(json);//输出:{“someName”:“somevalue”}

我在这里学习了
ExpandoObject
的技巧:

与NewtonSoft框架很好地集成的一个解决方案是提供一个定制的JObject转换器,它尊重
NamingStrategy

JObject自定义转换器
您可以在上找到一个正在工作的PoC。

难道
JObject
没有返回JSON的
ToString
方法吗?我认为在使用
JsonConvert.SerializObject()进行序列化期间,您不能“编辑”一个
JObject
。一个
JObject
已经被序列化,所以所有
jsonvert
所做的都是或多或少地逐字发送它。看见有关解决方法,请参见@MikeMcCaughan JObject.ToString将对象转换为json,但没有任何重载来接受设置对象;这个答案对我来说没有任何意义。作业对象的“原始JSON”是什么?这个术语在
JObject
文档中没有使用,也没有明显的含义,特别是考虑到
JObject
可以包含
JToken
之类的日期和GUID,它们不属于JSON规范,并且有多个可能的序列化。@MarkAmery您知道James编写/维护了JSON.NET,对吗^D我想他只是说,Json.NET并不认为
JObject
是一级对象,它会忽略您的序列化程序设置(可能考虑到作为
JObject
,它已经被序列化了)。如果要序列化
作业对象
,必须首先将其反序列化为真正的强类型。解释OP和我所看到的,并与Sipke和Goo的解决方案(和dbc的评论)相一致。@ruffin是的,我意识到James是项目作者。毫无疑问,
JObject
的“原始JSON”的概念对他来说是非常有意义的,基于JSON.NET代码库中使用的抽象,或者可能就在James的头脑中。但这并不能改变这样一个事实:对我们其他人来说,这基本上是胡说八道。虽然我很欣赏创作这本伟大的自传的努力,但这是一个非常突然的“答案”。无论这是不是最近添加到2016年,这个问题都可以通过为JObject添加一个序列化器转换器来回答,以便根据需要进行序列化-参见其他答案这似乎完美地回答了这个问题。刚刚在.NETCore3中实现了这个。但是,对于这个答案,如果它与所有JObject相关,您只需在序列化程序设置转换器中的NewtonsoftJson设置的根级别添加转换器<代码>MvcNewtonsoftJsonOptions.SerializerSettings.Converters.Add
public class JObjectNamingStrategyConverter : JsonConverter<JObject> {

private NamingStrategy NamingStrategy { get; }

public JObjectNamingStrategyConverter (NamingStrategy strategy) {
    if (strategy == null) {
        throw new ArgumentNullException (nameof (strategy));
    }
    NamingStrategy = strategy;
}

public override void WriteJson (JsonWriter writer, JObject value, JsonSerializer serializer) {
    writer.WriteStartObject ();
    foreach (JProperty property in value.Properties ()) {
        var name = NamingStrategy.GetPropertyName (property.Name, false);
        writer.WritePropertyName (name);
        serializer.Serialize (writer, property.Value);
    }
    writer.WriteEndObject ();
}

public override JObject ReadJson (JsonReader reader, Type objectType, JObject existingValue, bool hasExistingValue, JsonSerializer serializer) {
    throw new NotImplementedException ();
}
}
var snakeNameStrategy = new SnakeCaseNamingStrategy ();
var jsonSnakeSettings = new JsonSerializerSettings {
Formatting = Formatting.Indented,
Converters = new [] { new JObjectNamingStrategyConverter (snakeNameStrategy) },
   ContractResolver = new DefaultContractResolver {
       NamingStrategy = snakeNameStrategy
   },
};

var json = JsonConvert.SerializeObject (obj, jsonSnakeSettings);