C# 如何将WebAPI结果反序列化或格式化为特定的json结构
我使用的是.NETCore3.1WebAPI。从外部API获取数据。下面是我的代码控制器部分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
[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;
}
}