2

我正在为返回 JSON 数据的服务建模我的响应 DTO,如下所示:

{
    "response":
    {
        "metadataA" : "useless info a",
        "metadataB" : "useless info b",
        "metadataC" : "useless info c",
        ...
        "metadataZ" : "useless info z",
        "results" :
        [
            {
                "resultmetadataA" : "useless info a",
                "resultmetadataB" : "useless info b",
                "resultId": "a",
                "resultName": "A"
            },
            {
                "resultmetadataA" : "useless info a",
                "resultmetadataB" : "useless info b",
                "resultId": "b",
                "resultName": "B"
            }

        ]
    }
}

显然,我只希望我的 DTO 有一个带有 id 和名称的结果列表,如下所示:

class Response
{
    public List<Result> Results { get; set; }
}

class Result
{
    public string Id  { get; set; }
    public string Name  { get; set; }
}

是否有一些属性属性可以告诉服务堆栈 id 和 name 值的“路径”?


编辑 1

我正在尝试使用 ServiceStack.DataAnnotations 中的一些属性,但没有成功。尝试在属性中使用CompositeIndex (false, "response", "results")ResultsAliasResults,但结果一直为空。

请帮忙!

编辑 2

还尝试[DataContract]在响应和属性上直接[DataMember(Name = Id/Name)]解析这些数据,但它似乎不起作用。

4

3 回答 3

3

您可以使用字典:

public class ResponseDTO
{
    public List<Dictionary<string, string>> Results { get; set; }
}
于 2013-04-17T16:20:32.863 回答
1

首先,您的 JSON 无效"response": [不能是数组文字,而是包含对象属性。

如何调试序列化问题

目标是让您的架构匹配 JSON 的形状。不要试图猜测形状应该是什么,养成推断形状的习惯,尝试看看哪些属性会被序列化。如果没有属性被序列化,则执行相反的操作并填充和序列化您的 POCO 以查看它们预期的形状,然后将这些形状与原始 JSON 进行比较以查看它们的不同之处。有关调试序列化问题的其他提示,请参阅此答案。

var json = @"{
    ""response"":
    {
        ""metadataA"" : ""useless info a"",
        ""metadataB"" : ""useless info b"",
        ""metadataC"" : ""useless info c"",
        ""metadataZ"" : ""useless info z"",
        ""results"" :
        [
            {
                ""resultmetadataA"" : ""useless info a"",
                ""resultmetadataB"" : ""useless info b"",
                ""resultId"": ""a"",
                ""resultName"": ""A""
            },
            {
                ""resultmetadataA"" : ""useless info a"",
                ""resultmetadataB"" : ""useless info b"",
                ""resultId"": ""b"",
                ""resultName"": ""B""
            }

        ]
    }
}";

从上述 JSON 中推断出的类型:

public class MetadataResponse
{
    public Response Response { get; set; }
}

public class Response
{
    public string MetadataA { get; set; }
    public string MetadataB { get; set; }
    public string MetadataC { get; set; }
    public string MetadataZ { get; set; }
    public List<Result> Results { get; set; }
}

public class Result
{
    public string ResultmetadataA { get; set; }
    public string ResultmetadataB { get; set; }
    public string ResultId { get; set; }
    public string ResultName { get; set; }
}

使用上述类型测试 JSON 序列化:

var dto = json.FromJson<MetadataResponse>();
dto.PrintDump();

输出:

{
    Response: 
    {
        MetadataA: useless info a,
        MetadataB: useless info b,
        MetadataC: useless info c,
        MetadataZ: useless info z,
        Results: 
        [
            {
                ResultmetadataA: useless info a,
                ResultmetadataB: useless info b,
                ResultId: a,
                ResultName: A
            },
            {
                ResultmetadataA: useless info a,
                ResultmetadataB: useless info b,
                ResultId: b,
                ResultName: B
            }
        ]
    }
}
于 2013-04-17T19:44:33.537 回答
0

毕竟我发现没有办法为复杂的响应建模简单的 DTO,无论如何感谢所有的答案。

嗯,很遗憾我的 POCO 的结构依赖于 JSON 响应结构。但是,我可以抽象出响应结构并让我的所有 DTO 立即处理它。

从我的问题中考虑类似的 JSON 结构:

{
    "response":
    {
        ...,
        "results":
        [
            {
                "resourceType": "letter" ,
                "resources": ["a", "b", "c", ...]
            },
            {
                "resourceType": "number" ,
                "resources": ["1", "2", "3", ...]
            },
            ...
        ]    
    }
}

我抽象了常见的响应结构:

enum ResourceKind
{
    Letter,
    Number
}

public class BaseResponse
{
    public ResponseContent Response
    {
        get;
        set;
    }
}

public class ResponseContent
{
    public List<ResultContent> Results
    {
        get;
        set;
    }
}

public class ResultContent
{
    public ResourceKind Kind
    {
        get;
        set;
    }

    public List<string> Resources
    {
        get;
        set;
    }
}

最后得到了一个(几十个)特定服务器响应的简化实现:

public class SpecificResponse : BaseResponse
{
    public IEnumerable<SpecificResult> Results
    {
        get
        {
            foreach(ResultContent result in Response.Results)
            {
                SpecificResult newSpecificResult = new SpecificResult();
                newSpecificResult.Kind = result.Kind;
                newSpecificResult.Resources = result.Resources;
                yield return newCategory;
            }

            yield break;
        }
    }
}

我仍在寻找更好的东西,但现在这是我的解决方案。

于 2013-04-18T16:03:39.880 回答