我有一个端点,即使类型完全不同,它也会以空字符串的形式返回所有空值。例如,该数据
[{
"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'.
我尝试使用Contracts,ValueProviders和Converters时遇到了麻烦。我该怎么做呢?
这些链接都没有对我有帮助:
Customize Json.NET serialization to consider empty strings as null
Convert empty strings to null with Json.Net
Json Convert empty string instead of null
EDIT1:固定错字。
EDIT2:这是我尝试使用的转换器的代码:
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
进行“取消”。
答案 0 :(得分:0)
如果模型确实仅包含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));
}
}
}
}
}
}
如果模型的类型和字段种类繁多,则必须使用custom json converter。
无论哪种方式,示例中的JObject都可疑。它可能需要为其他类型,例如Object。
编辑:
由于类型繁多,因此您可能需要考虑在反序列化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();
答案 1 :(得分:0)
我终于找到了一个简单但棘手的解决方案。我使用了常规的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;
}