从Web API中的通用列表返回Json

14

我是这样构建我的列表的:

public static List<SearchFormula> SearchData(string searchString)
{
    var searchResults = new List<SearchFormula>();

    SqlDataReader drResults = FormulaUtility.SearchFormulas(searchString);

    if ((drResults != null) && (drResults.HasRows))
    {                
        while (drResults.Read())
        {
            searchResults.Add(new SearchFormula() 
            {  
                // id  use the GetValue function
                Title = drResults.GetString(1),
                Description = drResults.GetString(2), 
                Url = drResults.GetString(3)
                // total use the GetValue Function
                });
            }
        }
    return searchResults;
}

使用该对象:

public class SearchFormula
{
    public string Title { get; set; }

    public string Description { get; set; }

    public string Url { get; set; }
}

我开始使用了IHttpActionResult并返回了OK(results)函数。我相信这是让我进入困惑之路的原因。我已经成功地发送了一个ArrayList,但它的序列化方式不是我想象中的那样。

我尝试将其更改为ActionResult并尝试返回Json(result),其中Result是实际列表。

我想继续使用IhttpActionResult并使用OK()方法发送序列化数据。我还似乎在内置的json序列化程序和NewtonSoft json序列化程序之间存在冲突。

我应该使用什么?最简单的方法是什么,只需序列化通用列表并将结果传递到IHttpActionResult OK() 方法中?

我尝试了JavaScriptSerializer,但它返回的是XML而不是Json...

public class SearchController : ApiController
{
    public IHttpActionResult Get(string searchTerm)
    {            
        var jsonSerialiser = new JavaScriptSerializer();
        var jsonResult = jsonSerialiser.Serialize(SearchUtility.SearchData(searchTerm));

        if (jsonResult != null)
        {
            return Ok(jsonResult);
        }
        return NotFound();

    }
}

这是 Json.Net 示例:

public class SearchController : ApiController
{
    public IHttpActionResult Get(string searchTerm)
    {   
        var jsonResult = JsonConvert.SerializeObject(SearchUtility.SearchData(searchTerm));

        if (jsonResult != null)
        {
            return Ok(jsonResult);
        }
        return NotFound();        
    }
}

我尝试过使用MemoryStream......等等等等......没有一个干净、简单明了的方法,对于这个特定的解决方案也没有主题。

让我从这里开始......

如何将通用列表序列化为Json?

如何通过IHttpActionResult发送结果?

*更新*

这是我从Json.Net获取的序列化内容。但是格式有问题......即使是Fiddler也无法确定它是Json。我的标题看起来像这样(在Fiddler中):

Accept: application/json, text/javascript, /; q=0.01

"[{\"title\":\"Lacidofil®\",\"description\":\"Lacidofil® features Institut Rosell’s Lactobacillus helveticus and Lactobacillus rhamnosus. Both of these strains have been extensively studied in human clinical trials, possess an...\",\"url\":\"/products/product-detail.aspx?pid=103\"},{\"title\":\"MedCaps GI™\",\"description\":\"MedCaps GI™ features ingredients that are designed to nutritionally support the integrity and optimal function of the gastrointestinal lining. Fortified with nutrients such as l-glutam...\",\"url\":\"/products/product-detail.aspx?pid=114\"},{\"title\":\"OrganiX™ PhytoFood™\",\"description\":\"OrganiX PhytoFood is a convenient powdered formulation providing key nutrients to support a healthy lifestyle. This comprehensive formula incorporates an innovative blend of organi...\",\"url\":\"/products/product-detail.aspx?pid=271\"},{\"title\":\"Probio Defense™\",\"description\":\"Probio Defense™ is an optimal combination of probiotic bacteria that supports the immune system.\r\nThis product contains:\r\n\r\nLactobacillus helveticus Rosell-52 (3 billion)\r\nLactobacillu...\",\"url\":\"/products/product-detail.aspx?pid=102\"},{\"title\":\"ProbioMax Daily DF™\",\"description\":\"ProbioMax Daily DF™ is a vegetarian, dairy- and gluten-free, four-strain probiotic totaling 30 billion CFU† per capsule. Each vegetarian capsule is sealed in nitrogen-purged alu...\",\"url\":\"/products/product-detail.aspx?pid=181\"},{\"title\":\"ProbioMax DF™\",\"description\":\"ProbioMax DF™ is a vegetarian, dairy- and gluten-free, four-strain probiotic totaling 100 billion CFU† per capsule. Each vegetarian capsule is sealed in nitrogen-purged aluminum...\",\"url\":\"/products/product-detail.aspx?pid=184\"},{\"title\":\"ProbioMax Plus DF™\",\"description\":\"The multitude of healthful benefits attained by the individual supplementation of probiotic strains of bacteria, the non-pathogenic yeast, Saccharomyces boulardii, immunoglobulins,...\",\"url\":\"/products/product-detail.aspx?pid=185\"},{\"title\":\"Saccharomycin DF™\",\"description\":\"Saccharomycin DF™ is a lactose-free, stomach acid–resistant, stable, European patent-pending formula containing DNA-verified Saccharomyces boulardii. This probiotic yeast support...\",\"url\":\"/products/product-detail.aspx?pid=197\"}]"


你有没有研究过Json.Net? - Mike Schwartz
这是问题的一部分,我在默认和newtonsoft之间出现了冲突。 - Brett Spencer
1
我认为Web API默认已经使用了JSON.NET。在我的编写中,我总是返回我的对象,除非我特别想返回HTTP错误代码。这样,如果您的客户端想要使用XML而不是JSON,您就不需要再做任何工作了。 - Eugene S.
1
根据您的更新,Fiddler无法将其视为JSON的原因是因为它是一个JSON字符串,而不是JSON。请注意前导和尾随双引号以及其中所有转义引号。 - damienc88
@damienc88,谢谢。这就是我看到的东西,也是我为什么感到困惑的原因。为什么它要序列化成一个字符串?我该如何改变它只是Json?(我的Ajax调用无法通过id“解析”数据,因为整个字符串。) - Brett Spencer
请参见答案评论。 - Brett Spencer
2个回答

11
我采用这种看起来更简单的方法,不涉及更改你拥有的数据的json序列化器。
如果将对象作为列表返回,则默认的媒体类型格式化程序将根据客户端指定的内容类型处理序列化(前提是它是json或xml)。
为了演示目的,请添加以下方法以返回硬编码对象。
    // GET api/search
    public List<SearchFormula> Get(string searchTerm)
    {
        var searchItems = SearchData(searchTerm);
        return searchItems;
    }

    public static List<SearchFormula> SearchData(string searchString)
    {
        var searchResults = new List<SearchFormula>();

        searchResults.Add(new SearchFormula { Description = "desc1", Title = "title1", Url = "http://url.com" });
        searchResults.Add(new SearchFormula { Description = "desc2", Title = "title2", Url = "http://url.com" });

        return searchResults;

    }

然后在 Fiddler 中指定客户端接受 application/json,如下图所示,内容将以 json 的形式返回。

enter image description here

有关序列化的更多信息,请参见此处:

http://www.asp.net/web-api/overview/formats-and-model-binding/json-and-xml-serialization


标题是正确的。对象被正确填充。更新问题中的结果看起来如何。 - Brett Spencer
我在上面的 Fiddler 屏幕截图中突出显示了演示应用程序返回的 JSON 结果,即黄色框。那不是你想要的 JSON 吗? - hutchonoid
如果您将其更改为仅返回对象本身而不进行序列化,则应该可以正常工作。就像我上面的示例一样,唯一的区别是我没有从数据库中读取它们。 - hutchonoid
没问题,我认为这比你想象的要容易得多。只需不进行任何序列化调用并返回SearchUtility.SearchData(searchTerm)或OK(SearchUtility.SearchData(searchTerm)),默认的序列化程序将像我上面的示例一样启动。祝你好运。 :) - hutchonoid
1
在底层,它使用一个模型绑定器,根据客户端指定的内容类型将您的对象序列化为xml或json。请点赞并接受答案。我建议您使用jQuery getJson进行调用。祝你好运。 :) - hutchonoid
显示剩余6条评论

2

我通常使用这个扩展方法将对象序列化为JSON:

    public static class Extensions
{
    public static string SerializeToJson<T>(this T obj, DateTimeSerializationFormat format = DateTimeSerializationFormat.DotNet) where T : class
    {
        string result;
        var serializer = new DataContractJsonSerializer(typeof(T));
        using (var stream = new MemoryStream())
        {
            serializer.WriteObject(stream, obj);
            result = Encoding.UTF8.GetString(stream.ToArray());
        }

        if (formaat != DateTimeSerializationFormat.DotNet)
        {
            const string dotNetDateTimePattern = @"""\\/Date\((-?\d+)([\+-]\d{4})?\)\\/""";

            if (format ==DateTimeSerializationFormat.Iso8601 || format ==DateTimeSerializationFormat.Ruby))
            {
                var matchEvaluator = new MatchEvaluator(ConvertJsonDateToIso8601DateString);
                var regex = new Regex(dotNetDateTimePattern);
                resultaat = regex.Replace(resultaat, matchEvaluator);
                if (format == DateTimeSerializationFormat.Ruby && resultaat.Length > 10) // Ruby time
                {
                    result = Regex.Replace(result, @"([\+-]\d{1,2}\:\d{2})", " $0"); // Add an space before the timeZone, for example bv "+01:00" becomes " +01:00"
                }
            }

        }
        return result;
    }

    public enum DateTimeSerializationFormat
    {
        /// <summary>
        /// Example: "\/Date(1198908717056)\/" (aantal miliseconden na 1-1-1970)
        /// </summary>
        DotNet,
        /// <summary>
        /// Example: "1997-07-16T19:20:30.45+01:00"
        /// </summary>
        Iso8601,
        /// <summary>
        /// Example: "1997-07-16T19:20:30.45 +01:00"
        /// </summary>
        Ruby,
        ///// <summary>
        ///// Example: new Date(1198908717056) or other formats like new (date (1997,7,16)
        ///// </summary>
        //JavascriptDateObject
    }

不要忘记添加使用和引用:

System.Runtime.Serialization.Json;

1
除非您需要自定义JSON格式,否则不需要此功能。Web API中的MediaTypeFormatter实例处理序列化为JSON/XML和反序列化回CLR类型的操作。 - Sudhanshu Mishra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接