型が変わってしまったら、ただただ扱いづらいだけです。
実際にやりたいことは、どちらを読んでもList<Loginitem>
になることではないですか?
sendgrid - How to handle both a single item and an array for the same property using JSON.net - Stack Overflow
cs
1 using Newtonsoft . Json ;
2 using Newtonsoft . Json . Linq ;
3 using System ;
4 using System . Linq ;
5 using System . Collections . Generic ;
6
7 namespace Questions320367
8 {
9 class Program
10 {
11 static void Main ( )
12 {
13 var arrayJson = @"
14 {
15 ""LoginList"": {
16 ""LoginItem"": [
17 {
18 ""ID"": ""TEST01""
19 },
20 {
21 ""ID"": ""TEST02""
22 }
23 ]
24 }
25 }" ;
26 var result = JsonConvert . DeserializeObject < Rootobject > ( arrayJson ) ;
27 List < Loginitem > loginItem = result . LoginList . LoginItem ;
28
29 Console . WriteLine ( loginItem . Count ) ;
30 Console . WriteLine ( string . Join ( ", " , loginItem . Select ( x => x . ID ) ) ) ;
31
32
33 var singleJson = @"
34 {
35 ""LoginList"": {
36 ""LoginItem"": {
37 ""ID"": ""TEST01""
38 }
39 }
40 }" ;
41 result = JsonConvert . DeserializeObject < Rootobject > ( singleJson ) ;
42 loginItem = result . LoginList . LoginItem ;
43
44 Console . WriteLine ( loginItem . Count ) ;
45 Console . WriteLine ( string . Join ( ", " , loginItem . Select ( x => x . ID ) ) ) ;
46 }
47 }
48
49 public class Rootobject
50 {
51 public Loginlist LoginList { get ; set ; }
52 }
53 public class Loginlist
54 {
55 [ JsonConverter ( typeof ( SingleOrArrayConverter < Loginitem > ) ) ]
56 public List < Loginitem > LoginItem { get ; set ; }
57 }
58 public class Loginitem
59 {
60 public string ID { get ; set ; }
61 }
62
63 // [sendgrid - How to handle both a single item and an array for the same property using JSON.net - Stack Overflow](https://stackoverflow.com/questions/18994685/how-to-handle-both-a-single-item-and-an-array-for-the-same-property-using-json-n/18997172#18997172)
64 internal class SingleOrArrayConverter < T > : JsonConverter
65 {
66 public override bool CanConvert ( Type objectType ) => objectType == typeof ( List < T > ) ;
67 public override object ReadJson ( JsonReader reader , Type objectType , object existingValue , JsonSerializer serializer )
68 {
69 var token = JToken . Load ( reader ) ;
70 if ( token . Type == JTokenType . Array )
71 {
72 return token . ToObject < List < T > > ( ) ;
73 }
74 return new List < T > { token . ToObject < T > ( ) } ;
75 }
76
77 public override bool CanWrite => false ;
78 public override void WriteJson ( JsonWriter writer , object value , JsonSerializer serializer ) => throw new NotImplementedException ( ) ;
79 }
80 }
System.Text.Json版
c# - How to handle both a single item and an array for the same property using System.Text.Json? - Stack Overflow
cs
1 using System ;
2 using System . Collections ;
3 using System . Collections . Generic ;
4 using System . Linq ;
5 using System . Text . Json ;
6 using System . Text . Json . Serialization ;
7
8 namespace Questions320367
9 {
10 class Program
11 {
12 static void Main ( )
13 {
14 var arrayJson = @"
15 {
16 ""LoginList"": {
17 ""LoginItem"": [
18 {
19 ""ID"": ""TEST01""
20 },
21 {
22 ""ID"": ""TEST02""
23 }
24 ]
25 }
26 }" ;
27 var result = JsonSerializer . Deserialize < Rootobject > ( arrayJson ) ;
28 List < Loginitem > loginItem = result . LoginList . LoginItem ;
29
30 Console . WriteLine ( loginItem . Count ) ;
31 Console . WriteLine ( string . Join ( ", " , loginItem . Select ( x => x . ID ) ) ) ;
32
33
34 var singleJson = @"
35 {
36 ""LoginList"": {
37 ""LoginItem"": {
38 ""ID"": ""TEST01""
39 }
40 }
41 }" ;
42 result = JsonSerializer . Deserialize < Rootobject > ( singleJson ) ;
43 loginItem = result . LoginList . LoginItem ;
44
45 Console . WriteLine ( loginItem . Count ) ;
46 Console . WriteLine ( string . Join ( ", " , loginItem . Select ( x => x . ID ) ) ) ;
47 }
48 }
49
50 public class Rootobject
51 {
52 public Loginlist LoginList { get ; set ; }
53 }
54 public class Loginlist
55 {
56 [ JsonConverter ( typeof ( SingleOrArrayConverter < Loginitem > ) ) ]
57 public List < Loginitem > LoginItem { get ; set ; }
58 }
59 public class Loginitem
60 {
61 public string ID { get ; set ; }
62 }
63
64
65 // [c# - How to handle both a single item and an array for the same property using System.Text.Json? - Stack Overflow](https://stackoverflow.com/questions/59430728/how-to-handle-both-a-single-item-and-an-array-for-the-same-property-using-system)
66 public class SingleOrArrayConverter < TItem > : SingleOrArrayConverter < List < TItem > , TItem >
67 {
68 public SingleOrArrayConverter ( ) : this ( true ) { }
69 public SingleOrArrayConverter ( bool canWrite ) : base ( canWrite ) { }
70 }
71
72 public class SingleOrArrayConverter < TCollection , TItem > : JsonConverter < TCollection > where TCollection : class , ICollection < TItem > , new ( )
73 {
74 public bool CanWrite { get ; }
75
76 public SingleOrArrayConverter ( ) : this ( true ) { }
77 public SingleOrArrayConverter ( bool canWrite ) => CanWrite = canWrite ;
78
79 public override TCollection Read ( ref Utf8JsonReader reader , Type typeToConvert , JsonSerializerOptions options )
80 {
81 switch ( reader . TokenType )
82 {
83 case JsonTokenType . Null : return null ;
84 case JsonTokenType . StartArray :
85 var list = new TCollection ( ) ;
86 while ( reader . Read ( ) )
87 {
88 if ( reader . TokenType == JsonTokenType . EndArray ) break ;
89 list . Add ( JsonSerializer . Deserialize < TItem > ( ref reader , options ) ) ;
90 }
91 return list ;
92 default :
93 return new TCollection { JsonSerializer . Deserialize < TItem > ( ref reader , options ) } ;
94 }
95 }
96 public override void Write ( Utf8JsonWriter writer , TCollection value , JsonSerializerOptions options )
97 {
98 if ( CanWrite && value . Count == 1 )
99 {
100 JsonSerializer . Serialize ( writer , value . First ( ) , options ) ;
101 }
102 else
103 {
104 writer . WriteStartArray ( ) ;
105 foreach ( var item in value ) JsonSerializer . Serialize ( writer , item , options ) ;
106 writer . WriteEndArray ( ) ;
107 }
108 }
109 }
110 }