39

次のようにクラスを設定しています。

public class Foo
{
    public string string1 { get; set; }
    public string string2 { get; set; }
    public string string3 { get; set; }
}

Json.Net を使用して、次の Json 応答を逆シリアル化しています。

[
    {
        "number1": 1,
        "number2": 12345678901234567890,
        "number3": 3
    },
    {
        "number1": 9,
        "number2": 12345678901234567890,
        "number3": 8
    }
]

逆シリアル化コード:

string json = @"[
    {
        ""number1"": 1,
        ""number2"": 12345678901234567890,
        ""number3"": 3
    },
    {
        ""number1"": 9,
        ""number2"": 12345678901234567890,
        ""number3"": 8
    }
]"

List<Foo> foos = JsonConvert.DeserializeObject<List<Foo>>(json);

の値はnumber2を超えてInt64いますが、その値を取得することはあまり気にしません。number2プロパティを文字列にキャストする方法、または逆シリアル化中に完全に無視する方法はありますか?

[JsonConverter(typeof(string))]プロパティに属性を追加しようとしましたstring2が、次のエラーが表示されます: Error creating System.String。私も設定してみtypeof(decimal)ました。

私も使用してみ[JsonIgnore]ましたが、うまくいきません。

4

8 に答える 8

40

MissingMemberHandlingオブジェクトのプロパティを使用できJsonSerializerSettingsます。

使用例:

var jsonSerializerSettings = new JsonSerializerSettings();
jsonSerializerSettings.MissingMemberHandling = MissingMemberHandling.Ignore;

JsonConvert.DeserializeObject<YourClass>(jsonResponse, jsonSerializerSettings);

詳細はこちら

于 2013-11-26T12:13:12.673 に答える
11

これは不十分な回避策ですが、json を手動でロードする方法を作成できます。自動デシリアライザーなしでロードするにはデータが多すぎる場合は、不要なノードを削除してください。ただし、これははるかに遅いです。

public static List<Foo> FromJson(string input) {
    var json = JToken.Parse(input);
    json["key"].Remove();
    var foo = JsonConvert.DeserializeObject<List<Foo>>(json.ToString());

}

これは興味深い問題です。誰かがより良い解決策を持っているのではないかと思います。

于 2012-10-05T22:13:22.873 に答える
9

http://james.newtonking.com/json/help/index.html?topic=html/ReducingSerializedJSONSize.htmに基づいて、クラスを変更せずにプロパティを無視する Newtonsoft Json の推奨方法を次に示します。

これは、EF または Linq2Sql の遅延参照プロパティを無視するために使用されます。

public class DynamicContractResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, 
        MemberSerialization memberSerialization)
    {
        Func<Type,bool> includeProperty = t => t.IsValueType || t.Namespace.StartsWith("System") && t.Namespace.StartsWith("System.Data")==false; 
        IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
        var allProperties = properties.Select (p => new{p.PropertyName,Including=includeProperty(p.PropertyType), p.PropertyType});//.Dump("props");
        var warnProperties=allProperties.Where (a =>a.Including && a.PropertyType.IsValueType==false && a.PropertyType.Name.IsIgnoreCaseMatch("String")==false) ;

        //linq pad debugging helper
        //var propertyTypesSerializing= allProperties.Where (p => p.Including).Select (p => p.PropertyType).Distinct().OrderBy (p => p.Name).Dump();

        if(warnProperties.Any())
        {
            //LinqPad helper
            //Util.Highlight(warnProperties.ToArray()).Dump("warning flag raised, aborting");
            throw new ArgumentOutOfRangeException();
        }

        properties = properties.Where(p =>includeProperty(p.PropertyType)).ToList();
        return properties;
    }
}

すべての.Dump()呼び出しは linqpad デバッグ ヘルパーであり、メソッド呼び出しは必要ありません。

使用例:

var inactives = from am in Aspnet_Memberships
        join mm in Member_members on am.UserId equals mm.Member_guid
        where mm.Is_active==false && mm.Org_id==1
        select new{am,mm};
        //inactives.Take(4).ToArray().Dump();
        var serialized = JsonConvert.SerializeObject(
            inactives.Skip(1).Select(i => i.mm).First(), 
            new  JsonSerializerSettings()
            {
                ContractResolver = new DynamicContractResolver(), 
                PreserveReferencesHandling = PreserveReferencesHandling.None,
                ReferenceLoopHandling= ReferenceLoopHandling.Ignore
            }); 
            //.Dump();
于 2014-02-13T15:28:47.253 に答える
3

@Maslowのソリューションと同様に、別の汎用「無視」を使用できます。

var jsonResolver = new IgnorableSerializerContractResolver();
// ignore your specific property
jsonResolver.Ignore(typeof(Foo), "string2");
// ignore single datatype
jsonResolver.Ignore(typeof(System.Data.Objects.DataClasses.EntityObject));
var jsonSettings = new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, ContractResolver = jsonResolver };
于 2014-03-24T17:33:30.787 に答える
1

別;

ResponseAttribute にモデルまたは文字列パラメータがある場合

public class ResponseAttribute : Attribute { }

public class ModelItem
{
    [Response]
    public Guid Id { get; set; }
}

コード;

public class CustomJsonSerializer : JsonSerializerSettings
{
    public CustomJsonSerializer()
    {
        ContractResolver = new CustomContractResolver();
    }

    public CustomJsonSerializer(params string[] members)
    {
        ContractResolver = new CustomContractResolver(members);
    }

    public class CustomContractResolver : DefaultContractResolver
    {
        public string[] Members { get; set; }
        public CustomContractResolver(params string[] _members)
        {
            Members = _members;
        }

        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            JsonProperty property = base.CreateProperty(member, memberSerialization);

            if (Members?.Length > 0)
                property.ShouldSerialize = instance => { return Members.Contains(member.Name); };
            else
                property.ShouldSerialize = instance => { return member.GetCustomAttribute<ResponseAttribute>() != null; };

            return property;
        }
    }
}

使用する;

return new JsonResult(model, new CustomJsonSerializer());

また

return new JsonResult(model, new CustomJsonSerializer("Id","Test","Test2"));
于 2020-05-22T23:59:54.377 に答える
0

私は似たようなことに遭遇しましたが、私のクラスには List<> と Dictionary<> が含まれていました。データをスクラッチ オブジェクトにロードしてから必要なアイテムをプルする方が、その時点で見つけられた他の方法よりも簡単でした。

したがって、この例では、次のようなものです...

public class Foo
{
    public string string1 { get; set; }
    public string string2 { get; set; }
    public string string3 { get; set; }
}
List<Foo> foos = new List<Foo>();

List<Foo> tmp= JsonConvert.DeserializeObject<List<Foo>>(json);

foreach(Foo item in tmp)
{
    foos.string1 = tmp.string1;
    foos.string3 = tmp.string3;
}
于 2021-01-14T00:51:59.390 に答える