首页 > 解决方案 > 强大的表单 API JSON 响应 C# 对象

问题描述

我有一些从Formidable Forms API返回的 Json,但我正在努力将其转换为 (c#) 对象列表。返回的 json 不是对象数组,因此当我尝试反序列化为对象(使用 newtonsoft.json)时出现错误:

Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List...because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.

这是返回的 Json 的片段。

{
    "mrjgb": {
        "id": "50",
        "item_key": "mrjgb",
        "name": "John",
        "ip": "",
        "meta": {
            "first_name": "John",
            "middle_initial": "T",
            "last_name": "Doe",            
            "date": "August 15, 2019",
            "date-value": "2019-08-15"
        },
        "form_id": "15",
        "post_id": "0",
        "user_id": "0",
        "parent_item_id": "0",
        "is_draft": "0",
        "updated_by": "0",
        "created_at": "2019-08-15 18:10:59",
        "updated_at": "2019-08-15 18:10:59"
    },
    "9rs0q": {
        "id": "48",
        "item_key": "9rs0q",
        "name": "dsdds",
        "ip": "",
        "meta": {
            "first_name": "dsdds",
            "middle_initial": "",
            "last_name": "23112qead",            
            "date": "August 13, 2019",
            "date-value": "2019-08-13"
        },
        "form_id": "15",
        "post_id": "0",
        "user_id": "25",
        "parent_item_id": "0",
        "is_draft": "0",
        "updated_by": "25",
        "created_at": "2019-08-13 13:43:23",
        "updated_at": "2019-08-13 13:43:23"
    }
}

在这个片段中有两个对象,mrjgb 和 9rs0q,但是这些对象可以有任意数量并且它们没有设置名称。

有人可以指出我正确的方向吗?我做了很多尝试,都取得了不同程度的成功。

//List<Foo> foo = JsonConvert.DeserializeObject<List<Foo>>( response.Content );

//var Foo = JsonConvert.DeserializeObject<List<Foo>>( response.Content, new FooConverter() );
//var results = JsonConvert.DeserializeObject<List<dynamic>>( response.Content );

var FooList = new List<Foo>();
var results = JsonConvert.DeserializeObject<dynamic>( response.Content );

//var results33 = JsonConvert.DeserializeObject<Foo>( results );
//var Foos = JsonConvert.DeserializeObject<List<Foo>>( results, new FooConverter() );

foreach (var token in results )
{
    var Foo = JsonConvert.DeserializeObject<Foo>( token, new FooConverter() );
    //var Foo = JsonConvert.DeserializeObject<Foo>( results, new FooConverter() ); // passes all tokens, not just the one we want to convert
    FooList.Add( Foo );
}

//var Foo = JsonConvert.DeserializeObject<Foo>( response.Content );

编辑:

这篇文章的帮助下,我能够更接近一点。我可以获得一个密钥列表,但前提是我知道源名称(在这种情况下为 mrjgb),但名称是随机的,所以我不提前知道......

        JToken outer = JToken.Parse( response.Content );
        JObject inner = outer[ "mrjgb" ].Value<JObject>();

        List<string> keys = inner.Properties().Select( p => p.Name ).ToList();

标签: c#jsonjson.netformidable

解决方案


The API response is a JSON object, which translates to a .NET Dictionary<string, ?>. Instead of deserializing to a List or dynamic, use Dictionary<string, FormidableFormsResponse>:

var response = JsonConvert.DeserializeObject<Dictionary<string, FormidableFormsResponse>>(json);
Console.WriteLine($"{response.Keys.Count} items in the response");

var firstItem = response.ElementAt(0).Value;
Console.WriteLine(firstItem.Name);

var secondItem = response.ElementAt(1).Value;
Console.WriteLine(secondItem.Name);

I used QuickType to quickly generate the classes that represent the API response structure:

public class FormidableFormsResponse
{
    [JsonProperty("id")]
    public long Id { get; set; }

    [JsonProperty("item_key")]
    public string ItemKey { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("ip")]
    public string Ip { get; set; }

    [JsonProperty("meta")]
    public Meta Meta { get; set; }

    [JsonProperty("form_id")]
    public long FormId { get; set; }

    [JsonProperty("post_id")]
    public long PostId { get; set; }

    [JsonProperty("user_id")]
    public long UserId { get; set; }

    [JsonProperty("parent_item_id")]
    public long ParentItemId { get; set; }

    [JsonProperty("is_draft")]
    public long IsDraft { get; set; }

    [JsonProperty("updated_by")]
    public long UpdatedBy { get; set; }

    [JsonProperty("created_at")]
    public DateTimeOffset CreatedAt { get; set; }

    [JsonProperty("updated_at")]
    public DateTimeOffset UpdatedAt { get; set; }
}

public class Meta
{
    [JsonProperty("first_name")]
    public string FirstName { get; set; }

    [JsonProperty("middle_initial")]
    public string MiddleInitial { get; set; }

    [JsonProperty("last_name")]
    public string LastName { get; set; }

    [JsonProperty("date")]
    public string Date { get; set; }

    [JsonProperty("date-value")]
    public DateTimeOffset DateValue { get; set; }
}

Try it: fiddle


推荐阅读