我可以使用 set 方法代替 Json 属性 吗?
Can I use a set method instead of a Json Property?
我正在使用它来反序列化来自 Api 的 Json 响应。
var apiResponse = await GetAsync<MyResponseModel>(request);
在我的响应模型中,属性 是一个整数,但 api 出于某种原因将其格式化为浮点数。
所以它看起来像这样:
{
"Quantity": 6.000
}
现在我用这个技巧解析它:
[JsonProperty("Quantity")]
private float QuantityFloat {
set => Quantity = IsInt(value) ? (int) value: throw new ArgumentException("Tried to parse number to Quantity that is not an int.");
}
public int Quantity { get; set; }
private static bool IsInt(float value)
{
var x = (int) value;
var temp2 = value - x;
return temp2 <= 0;
}
我的 linter 现在抱怨:“只有 setter 的属性令人困惑且违反直觉。相反,如果可能,应该添加 属性 getter,或者 属性 应替换为 setter 方法。”
所以我问自己是否有更好更优雅的方法来做到这一点。
我建议创建一个可以处理整数和小数格式值的 JsonConverter<int>
:
(此解决方案适用于 System.Text.Json)
public class IntConverter : JsonConverter<int>
{
public override int Read(ref Utf8JsonReader reader, System.Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TryGetInt32(out var intVal))
{
return intVal;
}
// customize this part as necessary to satisfactorily deserialize
// the float value as int, or throw exception, etc.
float floatValue = reader.GetSingle();
return (int)floatValue;
}
public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
然后你可以用[JsonConverter(typeof(IntConverter))]
修饰你的属性,这将导致在序列化期间使用转换器:
public class Model
{
[JsonConverter(typeof(IntConverter))]
public int Quantity { get; set; }
}
像这样处理它可以消除对任何额外属性的需求,从而简化您的解决方案。如果您必须在多个地方处理这种情况,则尤其如此。
JSON.NET 解法:
public class IntConverter : JsonConverter<int>
{
public override int ReadJson(JsonReader reader, Type objectType, int existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Float)
{
// customize this part as necessary to satisfactorily deserialize
// the float value as int, or throw exception, etc.
double value = (double)reader.Value;
return (int)value;
}
long intVal = (long)reader.Value;
return (int)intVal;
}
public override void WriteJson(JsonWriter writer, int value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
使用以下型号:
public class Model
{
[JsonConverter(typeof(IntConverter))]
public int Quantity { get; set; }
}
我正在使用它来反序列化来自 Api 的 Json 响应。
var apiResponse = await GetAsync<MyResponseModel>(request);
在我的响应模型中,属性 是一个整数,但 api 出于某种原因将其格式化为浮点数。 所以它看起来像这样:
{
"Quantity": 6.000
}
现在我用这个技巧解析它:
[JsonProperty("Quantity")]
private float QuantityFloat {
set => Quantity = IsInt(value) ? (int) value: throw new ArgumentException("Tried to parse number to Quantity that is not an int.");
}
public int Quantity { get; set; }
private static bool IsInt(float value)
{
var x = (int) value;
var temp2 = value - x;
return temp2 <= 0;
}
我的 linter 现在抱怨:“只有 setter 的属性令人困惑且违反直觉。相反,如果可能,应该添加 属性 getter,或者 属性 应替换为 setter 方法。” 所以我问自己是否有更好更优雅的方法来做到这一点。
我建议创建一个可以处理整数和小数格式值的 JsonConverter<int>
:
(此解决方案适用于 System.Text.Json)
public class IntConverter : JsonConverter<int>
{
public override int Read(ref Utf8JsonReader reader, System.Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TryGetInt32(out var intVal))
{
return intVal;
}
// customize this part as necessary to satisfactorily deserialize
// the float value as int, or throw exception, etc.
float floatValue = reader.GetSingle();
return (int)floatValue;
}
public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
然后你可以用[JsonConverter(typeof(IntConverter))]
修饰你的属性,这将导致在序列化期间使用转换器:
public class Model
{
[JsonConverter(typeof(IntConverter))]
public int Quantity { get; set; }
}
像这样处理它可以消除对任何额外属性的需求,从而简化您的解决方案。如果您必须在多个地方处理这种情况,则尤其如此。
JSON.NET 解法:
public class IntConverter : JsonConverter<int>
{
public override int ReadJson(JsonReader reader, Type objectType, int existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Float)
{
// customize this part as necessary to satisfactorily deserialize
// the float value as int, or throw exception, etc.
double value = (double)reader.Value;
return (int)value;
}
long intVal = (long)reader.Value;
return (int)intVal;
}
public override void WriteJson(JsonWriter writer, int value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
使用以下型号:
public class Model
{
[JsonConverter(typeof(IntConverter))]
public int Quantity { get; set; }
}