在JSON数组中使用特定数据的服务堆栈响应DTO

本文关键字:数据 服务 堆栈 DTO 响应 数组 JSON | 更新日期: 2023-09-27 18:09:46

我正在为返回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。没有运气的数据注释。尝试使用CompositeIndex(false, "response", "results")在ResultsAliasResults属性,但结果一直为null。

请帮助!

编辑2

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

在JSON数组中使用特定数据的服务堆栈响应DTO

你可以使用字典:

public class ResponseDTO
{
    public List<Dictionary<string, string>> Results { get; set; }
}

首先您的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
            }
        ]
    }
}

毕竟我没有办法为复杂的响应建立简单的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;
        }
    }
}

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