.net JSON DataContract字符串和字符串数组的双类型

hc8w905p  于 2023-06-25  发布在  .NET
关注(0)|答案(1)|浏览(115)

我正在使用一个冒险团队的REST API。他们提供了两个端点,两者返回相似但不相等的响应。我正在使用DataContractJsonSerializer对响应进行反序列化。
终点A响应:

{
  "message": "Hello World."
}

终点B应答:

{
  "message": [
    "Hello World.",
    "Hello StackOverflow."
  ]
}

可以看到,端点A在message属性中提供了一个字符串,而端点B提供了一个字符串数组。
我真的很想使用相同的DataContract,但有没有办法做到这一点?

[DataContract]
public class Response
{
  [DataMember(Name = "message")]
  public string Message { get; set; } // Changing this to string[] fails as well.
}

当然,我得到了一个错误:
反序列化Response类型的对象时出错。应为命名空间“”中的结束元素“message”。在命名空间“”中找到元素“item”。
为了完整起见,这里是代码:

string jsonPayload = "{ 'Random': 'Payload' }";
HttpClient myHttpClient = getHttpClient();
HttpResponseMessage responseMsg = await myHttpClient.PostAsync("myApiPath", new StringContent(jsonPayload));

DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Response));
string rspJson = await responseMsg.Content.ReadAsStringAsync();
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(rspJson));
Response rsp = (Response)serializer.ReadObject(ms);
ma8fv8wu

ma8fv8wu1#

DataContractJsonSerializer内置了对多态原语和原语数组的支持,因此如果将Messages属性声明为object,则可以反序列化JSON:

[DataContract]
public class Response
{
    [DataMember(Name = "message")]
    public object Message { get; set; } // Changing this to string[] fails as well.
}

演示小提琴#1 here
这个模型并没有真正捕捉到Message应该是一个字符串或字符串数组的事实,所以你可能更喜欢使用一些替代属性来进行序列化,如下所示:

[DataContract]
public class Response
{
    [IgnoreDataMember]
    public string [] Messages { get; set; }
    
    [DataMember(Name = "message")]
    object SerializedMessages 
    { 
        get => Messages; 
        set => Messages = (value) switch
        {
            null => null,
            string s => new [] { s },
            string [] a => a,
            // Convert arrays of primitives to strings
            object [] a => a.Cast<IFormattable>().Select(f => Convert.ToString(f, CultureInfo.InvariantCulture)).ToArray(),
            _ => throw new ArgumentException(string.Format("Unknown value type {0}", value)),
        };
    }
}

请注意根据文件
对于大多数涉及序列化为JSON和从JSON反序列化的场景,我们推荐使用APIs in the System.Text.Json namespace
演示小提琴#2 here

相关问题