- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在使用 System.Net.WebClient.DownloadString 下载 JSON。我得到了一个有效的回应:
{
"FormDefinition": [
{
"$id":"4",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"Punchworks Form"
},
{
"$id":"6",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"Punchworks Form test second"
},
{
"$id":"46",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"any_Name"
},
{
"$id":"47",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"Punchworks Form test second"
},
{
"$id":"49",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"Testing Name ??´????? ???? ACEeišuu { [ ( ~ ! @ # "
},
{
"$id":"50",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"something new"
},
{
"$id":"56",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"Testing Name руÌÑÑкий 汉è¯æ¼¢èªž ĄČĘėįšųū { [ ( ~ ! @ # "
},
{
"$id":"57",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"Test Name"
},
{
"$id":"58",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"Unique Name - 12/16/2013 12:59:29 PM"
},
{
"$id":"59",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"Unique Name - 12/16/2013 1:01:18 PM"
},
{
"$id":"60",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"Unique Name - 12/16/2013 1:40:44 PM"
},
{
"$id":"61",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"Unique Name - 12/16/2013 1:43:46 PM"
},
{
"$id":"62",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"Unique Name - 12/16/2013 1:48:21 PM"
},
{
"$id":"63",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"Unique Name - 12/16/2013 1:57:00 PM"
},
{
"$id":"64",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"Unique Name - 12/16/2013 1:57:53 PM"
},
{
"$id":"65",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"Unique Name - 12/16/2013 1:58:46 PM"
},
{
"$id":"79",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"Testing Name1211"
},
{
"$id":"80",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"Testing Name1211"
},
{
"$id":"81",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"any_nami"
},
{
"$id":"90",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"Test_something3"
},
{
"$id":"91",
"Class":558,
"ClassDisplayLabel":"Punchworks",
"Name":"Test_something4"
}]
}
这是我的模型:
public class FormDefinitionList
{
[JsonProperty("FormDefinition")]
public List<FormDefinition> FormDefinitions { get; set; }
}
public class FormDefinition
{
[JsonProperty ("$id")]
public string Id { get; set; }
[JsonProperty ("Class")]
public int Class { get; set; }
[JsonProperty ("ClassName")]
public string ClassName { get; set; }
[JsonProperty ("ClassDisplayLabel")]
public string ClassDisplayLabel { get; set; }
[JsonProperty ("Definition")]
public string Definition { get; set; }
[JsonProperty ("Name")]
public string Name { get; set; }
}
当我这样做时一切正常:
string response = "json as above";
FormDefinitionList root = JsonConvert.DeserializeObject<FormDefinitionList> (response);
除了 Id ($id) 属性始终为空。起初我试图弄清楚我从服务器返回的美元符号是否不同,但情况似乎并非如此。我不确定从这里到哪里去,所以有什么想法吗?
提前致谢。
注意:如果我尝试使用 JavaScriptSerializer 之类的东西反序列化,它会完美运行,所以我相当确定我的模型或 JSON.net 有问题。虽然可能是错误的。
最佳答案
Json.Net 通常使用 $id
连同 $ref
作为元数据来保存 JSON 中的对象引用。所以当它看到 $id
它假定属性不是实际 JSON 属性集的一部分,而是一个内部标识符。因此它不会填充 Id
你的对象的属性,即使你包含了一个[JsonProperty]
属性表明它应该。
更新
截至 Json.Net 版本6.0.4 ,有一个新设置,您可以通过该设置指示反序列化器将这些“元数据”属性视为普通属性,而不是使用它们。您需要做的就是设置 MetadataPropertyHandling
设置为 Ignore
然后照常反序列化。
var settings = new JsonSerializerSettings();
settings.MetadataPropertyHandling = MetadataPropertyHandling.Ignore;
var obj = JsonConvert.DeserializeObject<FormDefinitionList>(json, settings);
在版本 6.0.4 之前,需要一种变通方法来解决此问题。该答案的其余部分讨论了可能的解决方法。如果您使用的是 6.0.4 或更高版本,则不需要解决方法,现在可以停止阅读。
我能看到的最简单的解决方法是对 "$id"
进行字符串替换与 "id"
(包括引号)在反序列化之前在 JSON 上,正如@Carlos Coelho 所建议的那样。由于您必须对每个响应都执行此操作,如果您走这条路,我建议您制作一个简单的辅助方法来避免代码重复,例如:
public static T Deserialize<T>(string json)
{
return JsonConvert.DeserializeObject<T>(json.Replace("\"$id\"", "\"id\""));
}
但是,由于您在评论中表示您不太热衷于使用字符串替换的想法,因此我研究了其他选项。我确实找到了另一种可能适合您的替代方案——自定义 JsonConverter
.转换器背后的想法是,它将尝试使用 Json.Net 的内置反序列化机制来创建和填充对象(无 ID),然后手动检索 $id
。来自 JSON 的属性并使用它来填充 Id
通过反射在对象上的属性。
这是转换器的代码:
public class DollarIdPreservingConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(FormDefinition);
}
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
object o = jo.ToObject(objectType);
JToken id = jo["$id"];
if (id != null)
{
PropertyInfo prop = objectType.GetProperty("Id");
if (prop != null && prop.CanWrite &&
prop.PropertyType == typeof(string))
{
prop.SetValue(o, id.ToString(), null);
}
}
return o;
}
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
我尝试编写转换器,使其适用于任何具有 $id
的对象-- 你只需要改变 CanConvert
相应的方法,以便除了 FormDefinition
之外,它还为您需要使用它的所有类型返回 true .
要使用转换器,您只需将它的实例传递给 DeserializeObject<T>
像这样:
FormDefinitionList root = JsonConvert.DeserializeObject<FormDefinitionList>(
json, new DollarIdPreservingConverter());
重要提示:您可能会想用 JsonConverter
来装饰您的类。属性而不是将转换器传递给 DeserializeObject
调用,但不要这样做——它会导致转换器进入递归循环,直到堆栈溢出。 (有一种方法可以让转换器使用属性,但您必须重写 ReadJson
方法以手动创建目标对象并填充其属性,而不是调用 jo.ToObject(objectType)
。这是可行的,但有点更乱。)
让我知道这是否适合您。
关于c# - JsonConvert.DeserializeObject<>(字符串)返回 $id 属性的空值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20686336/
编辑:澄清问题: 我已经覆盖了基类型的 JsonConverter(通过将 [JsonConverter(typeof(TConverter))] 应用于父类(super class)),但是当直接反
尝试使用 JsonConvert.PopulateObject 更新类属性时,未调用 JsonPathConverter,因此未完成填充。 示例类: [JsonConverter(typeof(Jso
我有一个我不能改变的类: public enum MyEnum { Item1 = 0, Item2 = 1 } public class foo { [JsonConvert
我正在使用 Json.NET (6.0.3) 进行序列化。我编写了一个自定义 JsonConverter TestConverter 来处理一些 BaseClass 的实例(通过将它们转换为整数 id
我有一个要求,我需要将默认值设置为下面的复杂属性 Instances使用 JsonProperty和 DefaultValue . 我知道我们可以为以下链接中提到的原始属性实现这一点,但需要知道我们如
我尝试查找上述比较,但找不到答案。 因为有多种方法可以获取 JObject(或所有继承自 JToken 的子类型)例如: Method1 . JObject.FromObject(obj); Meth
我已启用我的 API 以使用字符串值序列化/反序列化枚举。为此,我已将 JsonStringEnumConverter 添加到 API 的 Startup 类中受支持的 JsonConverter 列
我有一个 Employee 类,其中 Manager 属性本身是 Employee 类型 public class Employee { public string FirstName { g
我已经卡住模型(简化): part 'initial_data_model.freezed.dart'; part 'initial_data_model.g.dart'; @freezed clas
我正在尝试将两个字段和一个包含两个字段的捆绑对象发布到 Mailchimp 的 API 端点。 var store_id = ConfigurationManager.AppS
以下VB.NET代码使用Newtonsoft JSON.NET库,并在按钮单击事件处理程序中执行并阻止UI线程: Dim table As DataTable = Await Task.Factory
我遇到了一个问题,其中以下 ToJson() 方法返回的字符串仅为“{}” public class GenericRequest { publ
这个问题在这里已经有了答案: JSON Can't be Deserialized to Object, Needs Array? (2 个答案) 关闭 9 年前。 我有这个 Json 返回: [
我遇到了一个问题,其中以下 ToJson() 方法返回的字符串仅为“{}” public class GenericRequest { publ
这个问题在这里已经有了答案: JSON Can't be Deserialized to Object, Needs Array? (2 个答案) 关闭 9 年前。 我有这个 Json 返回: [
我创建了一个简单的类: public class TestObject { public TestObject(int id, string name, List list) {
我有一个像这样的 Json 对象: {"company": "My Company", "companyStart" : "2015/01/01", "employee" : { "name"
这是 json: { "odata.metadata": ".....", "value": [ { "AbsEntry": 10,
我有一个对象,其中包含一个具有 JsonConverter 属性的属性。对于数据读写,转换器不工作。声明的属性是 [JsonConverter(typeof(EpochDateTimeConverte
编辑:制作了一个更简单、更透明的示例案例 我正在尝试反序列化一组组件(属于一个实体)。其中一个组件是 Sprite 组件,它包含纹理和动画信息。我为此实现了一个 CustomConverter,因为原
我是一名优秀的程序员,十分优秀!