【问题标题】:JSON.NET changes type of a System.Object property automatically to System.StringJSON.NET 将 System.Object 属性的类型自动更改为 System.String
【发布时间】:2016-10-10 13:06:47
【问题描述】:

我有一个名为Arg 的类。 属性ArgValue 的类型为System.Object

public class Arg
{
    public string ArgName { get; set; }
    public object ArgValue { get; set; }
}

如果我想像这样反序列化 JSON 字符串:

string json = @"{""ArgName"":""arg"",""ArgValue"":""/something/more/than/a/string/""}";

var jsonSerializerSettings = new JsonSerializerSettings() { };

Arg arg = JsonConvert.DeserializeObject<Arg>(json, jsonSerializerSettings);

我得到的 Arg 对象的值如下:

  • ArgName 的类型为 string -> arg
  • ArgValue 的类型为 object {string} -> /something/more/than/a/string/

我不希望 JSON.NET 将其转换为 System.String。 如果属性是System.Object 类型,则不应将其转换为字符串。

最好让它保持原样,并且值的类型为:JToken(或JValue)。

是否有 JsonSerializerSettings 选项来配置此行为?

其他信息:

属性ArgValue中的字符串值是“不仅仅是一个字符串”,以后需要自己转换。 JsonConverter 不能在这里使用,因为此时我不知道对象的具体类型。后来我知道并需要使用JToken.ToObject&lt;MySpecialType&gt;()。 (比它被JsonConverter 正确转换)。

【问题讨论】:

  • 好吧,字符串和对象之间的转换意味着装箱拆箱,但在您的情况下,json 包含字符串,而不是对象,因此它已经完成了您想要实现的目标。
  • 那是因为不需要解析字符串值 - 字符串也是对象。如果您需要特定类型,请指定它,如果您不知道类型,请使用泛型。
  • 请说明您为什么想要这种行为?
  • 属性“ArgValue”中的字符串值是“不仅仅是一个字符串”,以后需要自己转换。 JsonConverter 不能在这里使用,因为此时我不知道对象的具体类型。后来我知道并需要使用 JToken.ToObject()。 (比它被 JsonConverter 正确转换)。

标签: c# json json.net deserialization


【解决方案1】:

正如我在评论中所说,您要反序列化的 json 字符串将被反序列化为具有两个属性的类的对象,两者都是字符串类型。这是因为当您指定"ArgName" : "arg" 时,arg 之间的两个引号标记了字符串类型的值。 ArgValue 也是这种情况,它也被序列化为字符串。

通过执行这行代码:

Arg arg = JsonConvert.DeserializeObject<Arg>(json, jsonSerializerSettings);

您收到一个 Arg 类型的对象 (arg),它与 ​​Arg 类型的经典对象完全相同。相当于做:

Arg arg = new Arg{ ArgName = "arg", ArgValue = "/something/more/than/a/string/" };

属性ArgValue期望对象的字符串赋值在反序列化的情况下是一样的,不涉及转换(或者更好的说cast),它只是boxing

【讨论】:

  • @user437899 请问,它是如何创建的,和对象属性一样?
  • 对不起,我按了“回车”,在我完成之前添加了评论:-)
  • 在客户端,类的创建方式如下: Arg arg = new Arg{ ArgName = "arg", ArgValue = new QualifiedName("/something/more/than/a/string/" ) };该值的类型为“namespace.Qualifiedname”。在所有管道步骤之后,在服务器端它应该是相同的类型。首先是解析,然后它应该使用 JsonConverter 实现来更改类型。但我不知道反序列化/解析时属性“ArgValue”的类型。
  • @user437899 我建议您将其保留为object,因为如果您在反序列化此属性时不知道它的类型,则将其存储为对象,然后进行转换之后是你唯一能做的。可以尝试反序列化为dynamic类型,但是会不太安全。
  • 好的,谢谢。我看到的唯一方法是自己在“较低级别”反序列化对象,然后我可以决定如何反序列化属性。 (应该是 JToken 类型)
【解决方案2】:

对于以后的转换,您可以使用

泛型

public class Arg<T>
{
    public string ArgName { get; set; }
    public T ArgValue { get; set; }
}

那么你可以传递目标类型如下:

JsonConvert.DeserializeObject<Arg<Qualifiedname>>(somestring);

public Arg<T> Deserialize<T>(string somestring){
  return JsonConvert.DeserializeObject<Arg<T>>(somestring);
}

保留为JToken

public class Arg
{
    public string ArgName { get; set; }
    public JToken ArgValue { get; set; }
}

稍后用JsonConvert反序列化它

public class Arg
{
    public string ArgName { get; set; }
    public string ArgValue { get; set; }
}

或者简单地将它作为字符串传递,直到你知道要解析什么类型..

【讨论】:

  • 我无法创建属性 JToken,因为“Arg”类是其他传输格式也使用的 DTO 类。
  • 那你能用泛型或者以后的反序列化吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-17
  • 2014-06-18
  • 1970-01-01
相关资源
最近更新 更多