Newtonsoftを明示的に使用するか、ASP.NET Web Apiのモデルバインディングメカニズムを介して、JSONを以下のC#オブジェクトに非正規化すると、文字列id
値が自動的にintに変換されます。タイプの不一致があるため、例外をスローしたり、エラーを発生させたりすることが予想されます。これは、JSONが仕様で機能することになっている方法ですか?そうでない場合、どうすればそのような自動変換を防ぐことができますか?
JSON:{"id":"4", "name":"a"}
C#モデル:int id; string name
これはJson.NETの機能です。プリミティブ型を逆シリアル化すると、可能な場合は常にプリミティブJSON値がターゲットのc#型に変換されます。文字列"4"
は整数に変換できるため、逆シリアル化は成功します。この機能が必要ない場合は、読み取られるトークンが本当に数値であることを確認する整数型の custom JsonConverter
を作成できます(またはnull
、 null許容値):
public class StrictIntConverter : JsonConverter
{
readonly JsonSerializer defaultSerializer = new JsonSerializer();
public override bool CanConvert(Type objectType)
{
return objectType.IsIntegerType();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
switch (reader.TokenType)
{
case JsonToken.Integer:
case JsonToken.Float: // Accepts numbers like 4.00
case JsonToken.Null:
return defaultSerializer.Deserialize(reader, objectType);
default:
throw new JsonSerializationException(string.Format("Token \"{0}\" of type {1} was not a JSON integer", reader.Value, reader.TokenType));
}
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
public static class JsonExtensions
{
public static bool IsIntegerType(this Type type)
{
type = Nullable.GetUnderlyingType(type) ?? type;
if (type == typeof(long)
|| type == typeof(ulong)
|| type == typeof(int)
|| type == typeof(uint)
|| type == typeof(short)
|| type == typeof(ushort)
|| type == typeof(byte)
|| type == typeof(sbyte)
|| type == typeof(System.Numerics.BigInteger))
return true;
return false;
}
}
コンバーターは4.00
のような値を整数として受け入れることに注意してください。ニーズに合わない場合は、JsonToken.Float
のチェックを削除してこれを変更できます。
次のように、モデルに直接適用できます。
public class RootObject
{
[JsonConverter(typeof(StrictIntConverter))]
public int id { get; set; }
public string name { get; set; }
}
または、コンバーターを JsonSerializerSettings
に含めて、すべての積分フィールドに適用します。
var settings = new JsonSerializerSettings
{
Converters = { new StrictIntConverter() },
};
var root = JsonConvert.DeserializeObject<RootObject>(json, settings);
最後に、JSONシリアライザー設定をWeb APIでグローバルに適用するには、たとえば ここ を参照してください。
最終的に必要な場合は、C#モデルを文字列にしてみてください。
ほとんどの人がこの種の振る舞いを望んでいるので、あなたが説明するのは機能です。確認していませんが、文字列からターゲットのプロパティタイプに自動的に変換しようとするConvert.ChangeType(strValue, propertyType);
のようなものを使用しているに違いありません。
文字列と同じように必要な場合は、Maksimのソリューションを使用してください。
モデルには、必要に応じて、両方のタイプを持つ追加のプロパティを組み込むこともできます。
public class Model
{
public int id { get; set; }
public string idStr => id.ToString();
public string name { get; set; }
}