its*_*ohn 8 c# webclient json.net
我正在使用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"
}]
}
Run Code Online (Sandbox Code Playgroud)
这是我的模型:
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; }
}
Run Code Online (Sandbox Code Playgroud)
我做的每件事都有效:
string response = "json as above";
FormDefinitionList root = JsonConvert.DeserializeObject<FormDefinitionList> (response);
Run Code Online (Sandbox Code Playgroud)
除了Id($ id)属性始终为null.起初我试图弄清楚我从服务器回来的美元符号是不同的,但事实并非如此.我不知道从哪里开始,所以任何想法?
提前致谢.
注意:如果我尝试使用JavaScriptSerializer之类的反序列化,它可以完美地工作,所以我很确定我的模型或JSON.net有问题.可能是错的.
Bri*_*ers 12
Json.Net通常$id与$ref元数据一起使用以保留JSON中的对象引用.因此,当它看到$id它假定该属性不是实际JSON属性集的一部分,而是内部标识符.因此Id,即使您包含[JsonProperty]指示它应该包含的属性,它也不会填充对象上的属性.
UPDATE
从Json.Net版本6.0.4开始,有一个新设置可以指示反序列化器将这些"元数据"属性视为普通属性而不是消耗它们.您需要做的就是将MetadataPropertyHandling设置设置为Ignore,然后照常反序列化.
var settings = new JsonSerializerSettings();
settings.MetadataPropertyHandling = MetadataPropertyHandling.Ignore;
var obj = JsonConvert.DeserializeObject<FormDefinitionList>(json, settings);
Run Code Online (Sandbox Code Playgroud)
在6.0.4版之前,需要一种解决方法来解决此问题.本答案的其余部分讨论了可能的解决方法.如果您使用的是6.0.4或更高版本,则不需要解决方法,现在可以停止阅读.
我可以看到的最简单的解决方法是在反序列化之前在JSON上"$id"用字符串替换"id"(包括引号),正如@Carlos Coelho建议的那样.由于你必须对每个响应都这样做,如果你走这条路线,我建议你做一个简单的帮助方法来避免代码重复,例如:
public static T Deserialize<T>(string json)
{
return JsonConvert.DeserializeObject<T>(json.Replace("\"$id\"", "\"id\""));
}
Run Code Online (Sandbox Code Playgroud)
但是,既然你在评论中说过你不是那么热衷于使用字符串替换的想法,那么我调查了其他选项.我找到了另一个可能适合你的替代方案 - 一个习惯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();
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试编写转换器,以便它可以用于任何具有的对象$id- 您只需要相应地更改CanConvert方法,以便它为除了需要使用它之外的所有类型返回true FormDefinition.
要使用转换器,您只需要传递它的实例,DeserializeObject<T>如下所示:
FormDefinitionList root = JsonConvert.DeserializeObject<FormDefinitionList>(
json, new DollarIdPreservingConverter());
Run Code Online (Sandbox Code Playgroud)
重要提示:您可能想要使用JsonConverter属性来装饰类,而不是将转换器传递给DeserializeObject调用,但不要这样做 - 它会导致转换器进入递归循环,直到堆栈溢出.(有一种方法可以让转换器使用该属性,但是您必须重写该ReadJson方法以手动创建目标对象并填充其属性而不是调用jo.ToObject(objectType).这是可行的,但更麻烦.)
如果这对您有用,请告诉我.
| 归档时间: |
|
| 查看次数: |
14465 次 |
| 最近记录: |