强大的表单 API JSON 对 C# 对象的响应

Formidable Forms API JSON Response to C# Object

我有一些 Json 从 Formidable Forms API 返回,但我正在努力将其转换为 (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 );

编辑:

this post 的帮助下,我离得更近了一点。我可以获得密钥列表,但前提是我知道源名称(在本例中为 mrjgb),但该名称是随机的,所以我无法提前知道它....

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

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

API 响应是一个 JSON 对象,转换为 .NET Dictionary<string, ?>。不要反序列化为 Listdynamic,而是使用 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);

我使用 QuickType 快速生成了代表 API 响应结构的 类:

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; }
}

试一试:fiddle

您可以通过 JsonConverter.DeserializeObject 方法解析它,returns 您是一个对象 (JObject)。然后你可以使用这个对象,其中 mrjgb 将是 JProperty9rs0q 将是另一个 JProperty 来自同一对象 (JObject)

var result = (JObject) JsonConvert.DeserializeObject(response.Content);

foreach (var r in result.Children())
{
     // Do what you need to do here,  r.First is the mrjgb/9rs0q/whatever object
     var _foo = r.First.ToObject<Foo>();
     FooList.Add( Foo );
}