如果解析Json中的某个字段的值

Jackile 2011-12-23 02:44:41
首先我知道可以直接利用写和 Json文件对应的字段实现直接反射,但是由于Json文件返回的字段不稳定,类无法控制这些未知字段,所以我需要override ReadJson方法,未知的字段可以用我自己的逻辑实现了,但是已知的字段无法反射成功了,囧~~

Json文件:
{
"result_ok": true,
"total_count": "4",
"page": 1,
"total_pages": 1,
"results_per_page": 50,
"data": [
{
"id": "1",
"contact_id": "",
"status": "Complete",
"is_test_data": "1",
"datesubmitted": "2011-12-09 02:07:33",
"[question(2)]": "Victor",
"[question(4), option(10001)]": "Oral Roberts",
"[question(4), option(10002)]": "",
"[question(4), option(10003)]": "Kansas St",
"[question(4), option(10004)]": "",
"[question(4), option(10005)]": "Notre Dame",
"[question(4), option(10007)]": "",
"[question(4), option(10008)]": "",
"[question(5)]": "Black pattern",
"[question(6), option(10012)]": "Logo1.gif",
"[question(6), option(10013)]": "Logo3.jpg",
"[question(6), option(10014)]": "",
"[question(6), option(10016)]": "",
"[question(8), question_pipe(\": "Man",
"[question(9), question_pipe(\": "NBA",
"[question(10), option(10024), question_pipe(\": "",
"[question(10), option(10025), question_pipe(\": "Muscle",
"[question(10), option(10026), question_pipe(\": "",
"[question(10), option(10027), question_pipe(\": "",
"[question(11)]": "",
"[question(11), question_pipe(\": "",
"[question(13)]": "20-99",
"[question(15)]": "Furniture",
"[question(16), option(10044)]": "",
"[question(17)]": "",
"[question(18), option(10053)]": "",
"[question(18), option(10054)]": "",
"[question(18), option(10056)]": "KINWAI",
"[url(\": "f299f5ef90291d40543fc731bb1fd755",
"[variable(\": "0",
"[variable(5)]": "10009",
"[variable(8)]": "",
"[variable(8), question_pipe(\": "10017",
"[variable(9)]": "",
"[variable(9), question_pipe(\": "10019",
"[variable(13)]": "10031",
"[variable(15)]": "10042",
"[variable(17)]": ""
}
]
}

我写了对应的

实体类:
[JsonObject(MemberSerialization.OptIn)]
[JsonConverter(typeof(SurveryResponseConverter))]
public class SurveyResponse
{
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "id")]
string _id;
public string ID
{
get { return _id; }
set { _id = value; }
}

[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "contact_id")]
public string ContactID { get; set; }

[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "status")]
public string Status { get; set; }

[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "is_test_data")]
public bool IsTestData { get; set; }

[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "date_submitted")]
public string DataSubmitted { get; set; }

[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public Dictionary<string, Question> Questions { get; set; }
}

转换类:

public class SurveryResponseConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(SurveyResponse);
}

public override bool CanRead
{
get { return true; }
}

public override object ReadJson(JsonReader jsonReader, Type objectType, object existingValue, JsonSerializer serializer)
{
var value = (SurveyResponse)existingValue;
if (value == null)
{
value = new SurveyResponse();
value.Questions = new Dictionary<string, Question>();
}

//string readResult = "{\n";
while (jsonReader.Read())
{
if (jsonReader.TokenType == JsonToken.PropertyName)
{
var name = jsonReader.Value.ToString();

if (name.StartsWith("[question("))
{
jsonReader.Read();//read the value

bool isMatchQuestion, isMatchQuestionAndOption, isMatchQuestionAndPipe, isMatchQuestionAndOptionAndPipe;

if (isMatchQuestion)
{
//TODO
}
else if (isMatchQuestionAndOption)
{
//TODO
}
else if (isMatchQuestionAndPipe)
{
//TODO
}
else if (isMatchQuestionAndOptionAndPipe)
{
//TODO
}
}
else if (name.StartsWith("[variable("))
{
//TODO
}
else if (name.StartsWith("[url("))
{
//TODO
}
else
{
var name = reader.Value.ToString();
var property = typeof(SurveyResponse).GetProperty(name);
property.SetValue(value, serializer.Deserialize(reader, property.PropertyType), null);

//虽然我尝试把类的属性改成和json文件一致(即ID改成id,ContactID改成contact_id),依然报同样的错误。
//问题在这里,我想通过属性反射来实现,结果提示:Unexpected token while deserializing object: Property Name
}
//readResult += (string)jsonReader.Value + ":";
}

}

return value;
}

public override bool CanWrite
{
get { return false; }
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
...全文
654 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
劉宏哲 2011-12-27
  • 打赏
  • 举报
回复
你还是应该想办法把值先从reader中取出来,是字符串也没关系,可以再进行类型转换。
另外你这种需要很灵活的数据传递,最好使用xml,json没有xml灵活。
熙风 2011-12-23
  • 打赏
  • 举报
回复
囧~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

顶。。。

Jackile 2011-12-23
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 liuhongzhe 的回复:]

之前理解错了,我感觉serializer.Deserialize(reader, property.PropertyType)部分写的不对。是不是应该用reader取值?
[/Quote]

这个只有这种用法,我之前用的是
value.Values[index] = serializer.Deserialize<string>(reader);

但是这个是类的属性,应该要看是string,还是int吧,
所以我就用了serializer.Deserialize(reader, property.PropertyType)

结果我查了Json的src,看到这段:

private object CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, object existingValue)
{
if (contract is JsonLinqContract)
return CreateJToken(reader, contract);

do
{
switch (reader.TokenType)
{
// populate a typed object or generic dictionary/array
// depending upon whether an objectType was supplied
case JsonToken.StartObject:
return CreateObject(reader, objectType, contract, member, existingValue);
case JsonToken.StartArray:
return CreateList(reader, objectType, contract, member, existingValue, null);
case JsonToken.Integer:
case JsonToken.Float:
case JsonToken.Boolean:
case JsonToken.Date:
case JsonToken.Bytes:
return EnsureType(reader.Value, CultureInfo.InvariantCulture, objectType);
case JsonToken.String:
// convert empty string to null automatically for nullable types
if (string.IsNullOrEmpty((string) reader.Value) &&
objectType != null &&
ReflectionUtils.IsNullableType(objectType))
return null;

// string that needs to be returned as a byte array should be base 64 decoded
if (objectType == typeof (byte[]))
return Convert.FromBase64String((string) reader.Value);

return EnsureType(reader.Value, CultureInfo.InvariantCulture, objectType);
case JsonToken.StartConstructor:
case JsonToken.EndConstructor:
string constructorName = reader.Value.ToString();

return constructorName;
case JsonToken.Null:
case JsonToken.Undefined:
if (objectType == typeof (DBNull))
return DBNull.Value;

return EnsureType(reader.Value, CultureInfo.InvariantCulture, objectType);
case JsonToken.Raw:
return new JRaw((string) reader.Value);
case JsonToken.Comment:
// ignore
break;
default:
throw new JsonSerializationException("Unexpected token while deserializing object: " + reader.TokenType);
}
} while (reader.Read());

throw new JsonSerializationException("Unexpected end when deserializing object.");
}

我就彻底晕了,也就是说 JToken.PropertyName直接抛异常啊,囧~~~
劉宏哲 2011-12-23
  • 打赏
  • 举报
回复
之前理解错了,我感觉serializer.Deserialize(reader, property.PropertyType)部分写的不对。是不是应该用reader取值?
劉宏哲 2011-12-23
  • 打赏
  • 举报
回复
你先在异常处打断点,看看serializer对象的类型是不是SurveryResponseConverter,再进行下一步判断。
Jackile 2011-12-23
  • 打赏
  • 举报
回复
自己顶一下~~

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧