Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将WebAPI结果反序列化或格式化为特定的json结构_C#_.net_Json_Asp.net Web Api_Asp.net Core Webapi - Fatal编程技术网

C# 如何将WebAPI结果反序列化或格式化为特定的json结构

C# 如何将WebAPI结果反序列化或格式化为特定的json结构,c#,.net,json,asp.net-web-api,asp.net-core-webapi,C#,.net,Json,Asp.net Web Api,Asp.net Core Webapi,我使用的是.NETCore3.1WebAPI。从外部API获取数据。下面是我的代码控制器部分 [HttpGet("transinfo/{id}")] public Object GettransactionData(int id) { var result=_transaction.GettransactionDetails(id).Result; List<PipeLineResponse> P = JsonConvert.Deseria

我使用的是.NETCore3.1WebAPI。从外部API获取数据。下面是我的代码控制器部分

[HttpGet("transinfo/{id}")]        
public Object GettransactionData(int id)
{
  var result=_transaction.GettransactionDetails(id).Result;
  List<PipeLineResponse> P = JsonConvert.DeserializeObject<List<PipeLineResponse>>(result.ToString());
  PipeLineResponseObject P1 = new PipeLineResponseObject();
  P1.data = P;
  return P1;
}
但我需要以下格式的数据

{
  "data": [
    {
      "TransactionID": "34540d40-7db8-44c1-9a2a-5072c2d01756",
      "fieldsList": [
        {
          "fieldId": "10",
          "fieldValue": "1001"
        },
        {
          "fieldId": "11",
          "fieldValue": "Test1"
        },
        {
          "fieldId": "12",
          "fieldValue": "Fixed1"
        }
      ]
    },
    {
      "TransactionID": "145800f9-c4a5-4625-84d7-29af5e674a14",
      "fieldsList": [
        {
          "fieldId": "10",
          "fieldValue": "1002"
        },
        {
          "fieldId": "11",
          "fieldValue": "Test2"
        },
        {
          "fieldId": "12",
          "fieldValue": "Fixed2"
        }
      ]
    }
  ]
}
我怎样才能做到这一点?可以使用JObject或JArray反序列化吗?请帮忙。 我尝试创建以下模型类,并尝试反序列化,但并没有得到预期的结果

public class PipeLineResponse
{
   public string TransactionID { get; set; }
   public List<Dictionary<string, string>> fields { get; set; }
}    

public class PipeLineResponseObject
{
 public List<PipeLineResponse> data { get; set; }
}
公共类管道响应
{
公共字符串TransactionID{get;set;}
公共列表字段{get;set;}
}    
公共类PipeLineResponseObject
{
公共列表数据{get;set;}
}

如何以任何DTO或Automapper都可以使用的格式创建json?请帮我拿些样品。

我在这里列出的解决方案采用了
DTO
方法。来自服务的响应被反序列化到DTO,DTO进一步被手动映射到我们发送到客户端的最终
ViewModel
。无论如何,这个实现是生产就绪的,还有改进的余地,我在评论中补充了这一点。但这让我们对如何处理此类场景有了详细的了解。我们正在使用
Newtonsoft.Json
,可以通过
NuGet
包管理器将其引入到您的项目中

DTO的结构
反序列化对
DTO的响应

我在这里提出的解决方案采用
DTO
方法。来自服务的响应被反序列化到DTO,DTO进一步被手动映射到我们发送到客户端的最终
ViewModel
。无论如何,这个实现是生产就绪的,还有改进的余地,我在评论中补充了这一点。但这让我们对如何处理此类场景有了详细的了解。我们正在使用
Newtonsoft.Json
,可以通过
NuGet
包管理器将其引入到您的项目中

DTO的结构
反序列化对
DTO的响应

您可以使用json字符串的自定义解析来实现这一点。但是,更简洁的方法可以是创建所需结构的ViewModel(对于您的情况,您可以使用一个属性
data
类型为
IEnumerable
的类,并且
T
是内部对象的类型),将服务的响应映射到您的viewmodel,并让默认序列化从那里接管。@SaiGummaluri:我在创建类模型后尝试过,但在如何创建类模型方面遇到了错误尝试一下,只需粘贴json,它将为您提供类structure@AcAnanth-您正在调用的服务的响应实际上将
字段
作为一个对象返回,其中所有字段都捆绑在一起。但是,您所需的结构有一个单独字段的数组。由于这种差异,您将得到一个错误。一种解决方法是将您的响应捕获到中间
DTO
(这可以是您使用
json2csharp
获得的结构)。手动或使用类似于
AutoMapper
的工具将此数据映射到ViewModel。您正在查看的需求是完全可行的。@AcAnanth-或者,如果您不想采用DTO路线,您可以利用
Newtonsoft.Json
并使用
LINQ to Json
:解析来自服务的响应并手动将其映射到ViewModel。您可以使用json字符串的自定义解析来实现这一点。但是,更简洁的方法可以是创建所需结构的ViewModel(对于您的情况,您可以使用一个属性
data
类型为
IEnumerable
的类,并且
T
是内部对象的类型),将服务的响应映射到您的viewmodel,并让默认序列化从那里接管。@SaiGummaluri:我在创建类模型后尝试过,但在如何创建类模型方面遇到了错误尝试一下,只需粘贴json,它将为您提供类structure@AcAnanth-您正在调用的服务的响应实际上将
字段
作为一个对象返回,其中所有字段都捆绑在一起。但是,您所需的结构有一个单独字段的数组。由于这种差异,您将得到一个错误。一种解决方法是将您的响应捕获到中间
DTO
(这可以是您使用
json2csharp
获得的结构)。手动或使用类似于
AutoMapper
的工具将此数据映射到ViewModel。您正在查看的需求是完全可行的。@AcAnanth-或者,如果您不想采用DTO路线,您可以利用
Newtonsoft.Json
并使用
LINQ to Json
:解析来自服务的响应并手动将其映射到ViewModel。谢谢你的回答。公共类字段这是用10,11和12硬编码的,对吗?我的更改在我的情况下,字段的数量可能会更改。有没有一种动态的方法来处理这个问题?@AcAnanth-如果你想处理不同的json结构,你可以通过创建一个自定义的
JsonConverter
(我们在上面的实现中使用默认的JsonConverter)。映射将使用
反射
,就像我在回答中的注释中提到的那样。看看这个,如果你需要进一步的帮助,请告诉我!谢谢你,兄弟。这真的很有帮助,谢谢你的回答。公共类字段这是用10,11和12硬编码的,对吗?我的更改在我的情况下,字段的数量可能会更改。有没有一种动态的方法来处理这个问题?@AcAnanth-如果你想处理不同的json结构,你可以通过创建一个自定义的
JsonConverter
(我们在上面的实现中使用默认的JsonConverter)。映射将使用
反射
,就像我在回答中的注释中提到的那样。看看这个,如果你需要,请告诉我
{
  "data": [
    {
      "TransactionID": "34540d40-7db8-44c1-9a2a-5072c2d01756",
      "fieldsList": [
        {
          "fieldId": "10",
          "fieldValue": "1001"
        },
        {
          "fieldId": "11",
          "fieldValue": "Test1"
        },
        {
          "fieldId": "12",
          "fieldValue": "Fixed1"
        }
      ]
    },
    {
      "TransactionID": "145800f9-c4a5-4625-84d7-29af5e674a14",
      "fieldsList": [
        {
          "fieldId": "10",
          "fieldValue": "1002"
        },
        {
          "fieldId": "11",
          "fieldValue": "Test2"
        },
        {
          "fieldId": "12",
          "fieldValue": "Fixed2"
        }
      ]
    }
  ]
}
public class PipeLineResponse
{
   public string TransactionID { get; set; }
   public List<Dictionary<string, string>> fields { get; set; }
}    

public class PipeLineResponseObject
{
 public List<PipeLineResponse> data { get; set; }
}
// RootDTO.cs
// This structure is directly based on the response obtained from remote service.

public class Fields
{
    [JsonProperty(PropertyName ="Fields.10")]
    public string Fields10 { get; set; }
    [JsonProperty(PropertyName = "Fields.11")]
    public string Fields11 { get; set; }
    [JsonProperty(PropertyName = "Fields.12")]
    public string Fields12 { get; set; } 
}

public class Datum
{
    public string Tranid { get; set; }
    public Fields fields { get; set; }
}

public class RootDTO
{
    [JsonProperty(PropertyName ="data")]
    public List<Datum> data { get; set; }
}
// PipelineResponse.cs
public class FieldsList
{
    public string fieldId { get; set; }
    public string fieldValue { get; set; }
}

public class ResponseDatum
{
    [JsonProperty(PropertyName = "TransactionID")]
    public string TransactionID { get; set; }
    public List<FieldsList> fieldsList { get; set; }
}
   
public class PipelineResponse
{        
    public List<ResponseDatum> data { get; set; }
}
// ...other code
var responseString = await httpResponseMessage.Content.ReadAsAsync<Object>();
// This is where the DTO object is created. This should be mapped to view model type.
var responseDTO = JsonConvert.DeserializeObject<RootDTO>(responseString);
public PipelineResponse ConvertResponseDTOToResponse(RootDTO responseDTO)
{
    // FieldId is being hardcoded here. Instead, you can use Reflection to 
    // fetch the property name, split on '.' and take the item at index 1.
    // Notice that DTO properties have "JsonProperty" attributes for this.
    try
    {        
        List<ResponseDatum> responseList = new List<ResponseDatum>();
        if (responseDTO != null)
        {
            // Reflection can be used to avoid hardcoding on 'fieldId'
            foreach (var item in responseDTO.data)
            {
                var responseDataObj = new ResponseDatum
                {
                    TransactionID = item.Tranid,
                    fieldsList = new List<FieldsList>
                    {
                        new FieldsList
                        {
                            fieldValue = item.fields.Fields10,
                            fieldId = "10"
                        },
                        new FieldsList
                        {
                            fieldValue = item.fields.Fields11,
                            fieldId = "11"
                        },
                        new FieldsList
                        {
                            fieldValue = item.fields.Fields12,
                            fieldId = "12"
                        }
                    }
                };
                responseList.Add(responseDataObj);
            }
        }

        // This object is what you return from your controller endpoint finally.
        // The serialized response of this object is of the json structure you need 
        return new PipelineResponse { data = responseList };
    }
    catch (Exception ex)
    {
        throw ex;
    }
}