2014-10-19 185 views
1

我想从API反序列化Json响应。反序列化JSON C#Json.net

的数据看起来像这样

{ 
"response": { 
    "6112": { 
     "ID": 6112, 
     "Title": "AdditionalPhotos" 
    }, 
    "5982": { 
     "ID": 5982, 
     "Title": "BikeRide" 
    }, 
    "total_records": "20", 
    "returned_count": 10, 
    "returned_records": "1-10" 

} 
} 

C#类:

public class Products 
{ 
    public class Product 
    { 
     public string Id { get; set; } 
     public string Title { get; set; } 
    } 
    public Product product { get; set; } 
} 

public class ss 
{ 
    public Dictionary<string, Products.Product> Response { get; set; } 
    public string total_records { get; set; } 

} 

序列化代码

ss res = Newtonsoft.Json.JsonConvert.DeserializeObject<ss>(jsonData()); 

我可以得到它没有total_records条目,低于deserializng工作一个Dictionary <string , Product>。但我无法弄清楚如何让它起作用。这是我得到的错误

将值“20”转换为键入“产品+产品”时出错。路径“response.total_records”

我知道为什么我得到的错误,但我不能确定我怎么能不打算在从total_records substringing下进行。我无法控制API数据。

编辑:你们是快,我仍然得到把班达

+1

属性中的元数据是这个JSON objcet有效吗?你有没有尝试http://json2csharp.com/? – 2014-10-19 19:11:45

+0

你的代码在哪里? – 2014-10-19 19:14:55

+0

谢谢Krzysztof,我没有尝试过,但我得到每个条目的个人课程。 @StephenKennedy。我知道错误是由于解串器试图将“20”转换为它不是的产品对象而导致的。我只是无法弄清楚如何将Json反序列化为对象的逻辑列表。 – 2014-10-19 19:23:37

回答

1

首先你JSON是不是有效的,它应该是这样的

{ 
"response":{ 
    "6112":{ 
     "ID":"6112", 
     "Title":"Additional Photos", 
    }, 
    "5982":{ 
     "ID":"5982", 
     "Title":"Bike Ride", 
    }, 
    "total_records": "20", 
    "returned_count": "10", 
    "returned_records": "1-10", 
    } 
} 

如果你的意思是响应包含列出它应该是这样的

{ 
"response":{ 
    "myArray": [ 
     { 
      "ID":"6112", 
      "Title":"Additional Photos", 
     }, 
     { 
      "ID":"5982", 
      "Title":"Bike Ride", 
     } 
    ], 
    "total_records": "20", 
    "returned_count": "10", 
    "returned_records": "1-10", 
    } 
} 

所以,你的代码看起来象

public class MyArray 
{ 
    public string ID { get; set; } 
    public string Title { get; set; } 
} 

public class Response 
{ 
    public List<MyArray> myArray { get; set; } 
    public string total_records { get; set; } 
    public string returned_count { get; set; } 
    public string returned_records { get; set; } 
} 

public class RootObject 
{ 
    public Response response { get; set; } 
} 
+0

同意JSON应该看起来像第二个例子(产品作为数组或字典),但OP表示他无法控制从API接收的数据:/ – 2014-10-19 19:37:59

+0

感谢@Mzf。斯蒂芬是正确的。没有访问权限。 – 2014-10-19 19:39:35

+0

@AndrewMacNaughton - 对于使用API​​-如果响应应该是JSON,但它无效,则不能使用内置的方式。如果这是一个有效的Json - 你知道API会返回多少ID吗?它可以改变吗? – Mzf 2014-10-19 19:44:21

-1

在我看来,这是JSON文件应该如何看起来像:

{ 
"response": { 
    "5982": { 
     "ID": 5982, 
     "Title": "BikeRide" 
    }, 
    "6112": { 
     "ID": 6112, 
     "Title": "AdditionalPhotos" 
    }, 
    "total_records": "20", 
    "returned_count": 10, 
    "returned_records": "1-10" 
} 
} 

,这是类看起来应该像

public class __invalid_type__5982 
{ 
public int ID { get; set; } 
public string Title { get; set; } 
} 

public class __invalid_type__6112 
{ 
    public int ID { get; set; } 
    public string Title { get; set; } 
} 

public class Response 
{ 
public __invalid_type__5982 __invalid_name__5982 { get; set; } 
public __invalid_type__6112 __invalid_name__6112 { get; set; } 
public string total_records { get; set; } 
public int returned_count { get; set; } 
public string returned_records { get; set; } 
} 

public class RootObject 
{ 
public Response response { get; set; } 
} 
+2

我怀疑5982和6112是否固定,他们肯定会依赖于他要求的产品? – 2014-10-19 19:35:47

+1

看起来像你刚从Json2Csharp复制粘贴。很显然,像5982这样的ID可以随时改变。 – 2014-10-19 19:36:19

+0

是的,现在我们有大约300种产品... – 2014-10-19 19:41:17

0

如果你有超过API响应控制,那么请参考Mzf的答案。

如果您无法控制API,则可能无法一次执行此特定的反序列化。你可能必须循环。

这是我的要求。

更新

修改我的方法:

创建从字典<字符串,产品>继承的类响应,并添加元数据部件,如total_records,records_count到它的公共属性。并创建了一个可以将JObject反序列化为Response类的JsonConverter。

用于反串行化逻辑是非常简单的:

  • 提取元数据部分,如total_records,records_count给变量。
  • 然后从JObject中删除这些元数据,以使键值变得均匀。
  • 现在Json.net将很容易将JObject序列化为Response对象,因为键值是同质的。
  • 指定先前提取到Response对象

    public void Deserialize() 
    { 
        var json = @"{ 
         'response':{ 
         '6112':{ 
          'ID':6112, 
          'Title':'Additional Photos', 
         }, 
         '5982':{ 
          'ID':5982, 
          'Title':'Bike Ride', 
         }, 
         'total_records': '20', 
         'returned_count': 10, 
         'returned_records': '1-10', 
         } 
        }"; 
        var responseObj = Newtonsoft.Json.JsonConvert.DeserializeObject<ss>(json, new ResponseConverter()); 
    
    } 
    
    public class Response : Dictionary<string, Product> 
    { 
        public int total_records { get; set; } 
    
        public int returned_count { get; set; } 
    
        public string returned_records { get; set; } 
    } 
    
    public class Product 
    { 
        public string Id { get; set; } 
        public string Title { get; set; } 
    } 
    
    
    public class ss 
    { 
        public Response Response { get; set; } 
    } 
    
    public class ResponseConverter : Newtonsoft.Json.JsonConverter 
    { 
        private Response CreateResponse(Newtonsoft.Json.Linq.JObject jObject) 
        { 
         //preserve metadata values into variables 
         int total_records = jObject["total_records"].ToObject<int>(); 
         var returned_records = jObject["returned_records"].ToObject<string>(); 
         var returned_count = jObject["returned_count"].ToObject<int>(); 
    
         //remove the unwanted keys 
         jObject.Remove("total_records"); 
         jObject.Remove("returned_records"); 
         jObject.Remove("returned_count"); 
    
         //once, the metadata keys are removed, json.net will be able to deserialize without problem 
         var response = jObject.ToObject<Response>(); 
    
         //Assign back the metadata to response object 
         response.total_records = total_records; 
         response.returned_count = returned_count; 
         response.returned_records = returned_records; 
    
         //.. now person can be accessed like response['6112'], and 
         // metadata can be accessed like response.total_records 
    
         return response; 
        } 
    
        public override bool CanConvert(Type objectType) 
        { 
         return objectType == typeof(Response); 
        } 
    
        public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) 
        { 
         var jObject = Newtonsoft.Json.Linq.JObject.Load(reader); 
    
         Response target = CreateResponse(jObject); 
    
         serializer.Populate(jObject.CreateReader(), target); 
    
         return target; 
        } 
    
        public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) 
        { 
         throw new NotImplementedException(); 
        } 
    }