【问题标题】:How to fill object from contents of a string and populate a List?如何从字符串的内容中填充对象并填充列表?
【发布时间】:2019-07-12 11:00:09
【问题描述】:

我有一个字符串,我通过 HTTP Web 请求发送了一个使用 GZIP 压缩的字符串,其中包含以下数据:

[Route("Test")]
public IActionResult Test()
{
 var data = "[0].meetingDate=2019-07-12&[0].courseId=12&[0].raceNumber=1&[0].horseCode=000000331213&[1].meetingDate=2019-07-12&[1].courseId=12&[1].raceNumber=1&[1].horseCode=000000356650";

  try
    {
        var req = WebRequest.Create("https://localhost:44374/HorseRacingApi/Prices/GetPriceForEntries");
        req.Method = "POST";
        req.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
        req.Headers.Add(HttpRequestHeader.ContentEncoding, "gzip");

        if (!string.IsNullOrEmpty(data))
        {
            var dataBytes = Encoding.ASCII.GetBytes(data);

            using (var requestDS = req.GetRequestStream())
            {
                using (var zipStream = new GZipStream(requestDS, CompressionMode.Compress))
                {
                    zipStream.Write(dataBytes, 0, dataBytes.Length);
                }

                requestDS.Flush();
            }
        }

        HttpWebResponse response = (HttpWebResponse)req.GetResponse();
        Stream receiveStream = response.GetResponseStream();

        StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);

        Debug.WriteLine("Response stream received.");
        Debug.WriteLine(readStream.ReadToEnd());
        response.Close();
        readStream.Close();

        return Ok("Sent!");
    }
    catch(Exception ex)
    {
        throw ex;
    }
}

我在这个函数中接收http数据并解压:

[HttpPost]
[Route("GetPriceForEntries")]
[DisableRequestSizeLimit]
public JsonResult GetPriceForEntries(bool? ShowAll)
{
    string contents = null;

    using (GZipStream zip = new GZipStream(Request.Body, CompressionMode.Decompress))
    {
        using (StreamReader unzip = new StreamReader(zip))
        {
            contents = unzip.ReadToEnd();
        }
    }


   //CONVERT CONTENTS TO LIST HERE?

    return Json("GOT");
}

我有一个对象/模型设置:

public class JsonEntryKey
{
    public DateTime meetingDate { get; set; }
    public int courseId { get; set; }
    public int raceNumber { get; set; }
    public string horseCode { get; set; }
}

如何将此“字符串”转换为上面的 List 对象?

我之所以通过压缩发送这些数据是因为有时数据会非常大。

干杯

编辑:这是我创建所有者“转换器”的尝试

 //Convert string to table.
        string[] unzipString = contents.Split('=','&');
        List<Core.Models.JsonEntryKey> entries = new List<Core.Models.JsonEntryKey>();

        for (int i = 1; i < entries.Count; i += 8)
        {
            DateTime meetingDate = Convert.ToDateTime(entries[i]);
            int courseId = int.Parse(unzipString[i + 2]);
            int raceNumber = int.Parse(unzipString[i + 4]);
            string horseCode = unzipString[i + 6];

            entries.Add(new Core.Models.JsonEntryKey
            {
                meetingDate = meetingDate,
                courseId = courseId,
                raceNumber = raceNumber,
                horseCode = horseCode
            });
        }

有没有更好的办法?

【问题讨论】:

  • 首先你必须从你的字符串中取出需要的信息。例如使用正则表达式。然后你可以创建你的列表。您可以尝试将其拆分为 [0],这样您就只有属性名称和值。
  • 您是否以任何方式限制以 JSON 格式发送该列表?如果是,您必须制作一个自定义转换器。
  • 您需要从该字符串中获得的确切信息是什么?如果没有自定义转换器,您无法将此字符串直接转换为列表。
  • 正如 adSad 所说,为什么没有 JSON 格式?另外您尝试过什么,您的问题在哪里?
  • 我已经更新了我的问题。如果我们可以将数据字符串转换为JSON字符串并通过json发送然后转换为列表我可以吗?

标签: c# string http gzip


【解决方案1】:

基本解析可以分3步完成。

1) Split'&amp;' 的整个字符串

string [] parts = data.Split('&')

你最终得到了单一的部分:

[0].meetingDate=2019-07-12
[0].courseId=12
[0].raceNumber=1
[0].horseCode=000000331213
[1].meetingDate=2019-07-12
[1].courseId=12
[1].raceNumber=1
[1].horseCode=000000356650

2) 现在您可以GroupBy 括号中的数字,因为它似乎表示对象的索引[0][1]、...。由'.' 拆分并取第一个元素:

var items = parts.GroupBy(x => x.Split('.').First());

3) 现在对于每个组(基本上是关于每个对象的属性信息的集合),您需要遍历属性,通过反射找到相应的属性并设置值。最后:不要忘记将新创建的对象收集到一个集合中:

List<JsonEntryKey> collection = new List<JsonEntryKey>();
foreach (var item in items)
{
    var entry = new JsonEntryKey();
    foreach (var property in item)
    {
        // here the position propInfo[1] has the property name and propInfo[2] has the value
        string [] propInfo = property.Split(new string[] {"].", "="}, StringSplitOptions.RemoveEmptyEntries);
        // extract here the corresponding property information  
        PropertyInfo info = typeof(JsonEntryKey).GetProperties().Single(x => x.Name == propInfo[1]);
        info.SetValue(entry, Convert.ChangeType(propInfo[2], info.PropertyType));
    }       
    collection.Add(entry);      
}

您的字符串的结果在 LINQPad 转储中看起来像这样:

【讨论】:

  • 感谢您的回答。我做了类似的事情,我更新了我的帖子。我猜你的方法比我的好很多?
  • @ZackAntonyBucci “好多了”我真的不知道。取决于如何评价它的观点。我想我的解决方案不太依赖于字符串中属性的顺序。如果订单可能有一天会改变,那么像您的解决方案中的硬编码索引将不再起作用。我只是使用了这样一个事实,即您将类中的属性完全按照字符串中出现的方式命名
  • @ZackAntonyBucci 我想如果你一开始就发布了所有这些代码,你可能会为你省去所有这些反对票,可能......但再想一想,SO 上的人真的很喜欢否决票:D
【解决方案2】:

我想分享的另一种解决方案是基于Regex 的解决方案。我为此字符串构建的正则表达式将在字符串末尾附加&amp; 字符后起作用,并且基于正则表达式逻辑,将从字符串中解析出所需的数据。这只是一个示例,说明如何使用正则表达式处理字符串场景。关于官方规格的性能:

.NET 中的正则表达式引擎是一个功能强大、功能齐全的工具,它根据模式匹配而不是比较和匹配文字文本来处理文本。在大多数情况下,它可以快速有效地执行模式匹配。但是,在某些情况下,正则表达式引擎可能看起来很慢。在极端情况下,它甚至会停止响应,因为它会在数小时甚至数天的过程中处理相对较小的输入。

正则表达式的性能取决于字符串的长度和正则表达式的复杂度。关于你的字符串data,我这里准备了一个DEMO

代码如下:

using System;
using System.Text.RegularExpressions;

public class Program
{
    public static void Main()
    {
         var data = "[0].meetingDate=2019-07-12&[0].courseId=12&[0].raceNumber=1&[0].horseCode=000000331213&[1].meetingDate=2019-07-12&[1].courseId=12&[1].raceNumber=1&[1].horseCode=000000356650";
         var dataRegex=data+"&";
         //Console.WriteLine(dataRegex);
         showMatch(dataRegex, @"(?<==)(.*?)(?=&)");
    }

     private static void showMatch(string text, string expr) {
         MatchCollection mc = Regex.Matches(text, expr);

         foreach (Match m in mc) {
            Console.WriteLine(m);
         }
      }
}

输出是:

2019-07-12
12
1
000000331213
2019-07-12
12
1
000000356650

使用的正则表达式:(?&lt;==)(.*?)(?=&amp;)

解释:

  1. Positive Lookbehind (?&lt;==):在字面上匹配字符 =(区分大小写)
  2. 第一个捕获组(.*?).*? 匹配任何字符(行终止符除外)。 *? Quantifier — 匹配零次和无限次,尽可能少,根据需要扩展。
  3. 正向预测 (?=&amp;):匹配字符 &amp; 字面意思(区分大小写)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-12
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    • 1970-01-01
    • 2019-04-11
    • 1970-01-01
    • 2010-10-19
    相关资源
    最近更新 更多