Json.net 将所有空字符串解压缩为 null



我有一个端点,它将所有空值作为空字符串返回,即使类型完全不同。例如,此数据

[{
"field1": 3,
"field2": "bob",
"field3": ["alpha", "beta", "gamma"],
"field4": { "some": "data" }
},
{
"field1": "", // needs to be deserialized as null
"field2": "", // same
"field3": "", // ..
"field4": "" // ..
}]

需要序列化为(数组(模型,例如:

public class Root
{
public int? Field1 { get; set; }
public string Field2 { get; set; }
public string[] Field3 { get; set; }
public JObject Field4 { get; set; }
}

但 Json.Net 抛出了一个例外:

Unhandled Exception: Newtonsoft.Json.JsonSerializationException: Error setting value to 'Field4' on 'Root'. ---> System.InvalidCastException: Unable to cast object of type 'Newtonsoft.Json.Linq.JValue' to type 'Newtonsoft.Json.Linq.JObject'.

我尝试使用合约、价值提供者和转换器,但没有运气。我该怎么做呢?

这些链接都没有帮助我:
自定义 Json.NET 序列化以将空字符串视为空
使用 Json.Net
JSON 将空字符串转换为空 转换空字符串而不是空

编辑1:修正错别字。

编辑2:这是我尝试使用的转换器的代码:

public class VdfNullConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
// ...
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.String && (reader.Value as string == ""))
return null;
// I don't know what to do here
}
public override bool CanConvert(Type objectType)
{
return true;
}
}

我的问题是我不知道如何处理数据实际上不是空字符串的情况。在这种情况下,我需要调用其他转换器,但我无法在ReadJson中途"取消"。

我终于找到了一个简单但笨拙的解决方案。我使用了一个常规的 JsonConverter,并使用如下代码进行回溯:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.String && (reader.Value as string == ""))
return null;
skip = true;
return serializer.Deserialize(reader, objectType);
}
private bool skip = false;
public override bool CanConvert(Type objectType) // If this is ever cached, this hack won't work.
{
if (skip)
{
skip = false;
return false;
}
return true;
}

如果您的模型实际上只包含 4 个字段,则可以考虑使用序列化属性

public class Root{
[JsonIgnore]
public int? Field1 {get;set;}
[JsonProperty("field1")]
protected string Field1Data{
{
get { return Field1?.ToString(); }
set { 
if (string.IsNullOrEmpty(value))
Field1 = null;
else {
int parsed;
if (Int32.TryParse(value, out parsed)){
Field1 = parsed;
} else {
throw new ArgumentException($"{value} could not be parsed", nameof(Field1));
}
}
} 
}
} 
}

如果您的模型具有更多种类的类型和字段,则必须使用自定义 json 转换器。

无论哪种方式,样本中的 JObject 看起来都很可疑。它可能需要是其他类型,例如对象。

编辑:

由于类型种类繁多,因此您可能需要考虑在反序列化 json 之前对其进行预处理,因为使用转换器需要更具体。

您可以将输入解析为 JObject,选择所有空字符串值并删除属性:

var jobj = JObject.Parse(File.ReadAllText("sample.json"));
var tokens = jobj.SelectTokens("$..[?(@=~/^$/)]").ToList();
tokens.ForEach(t=>t.Parent.Remove()); // you could filter some of the removals if you need to 
string nowUseThisAsYourImpup = jobj.ToString();  

最新更新