将Json字符串转换为对象的C#方法

3

我一直在尝试让这个工作正常运行,但已经4天了,但我似乎无法弄清楚。我通过API接收到一个JSON字符串,并希望将数据解析为不同的字符串和整数:

示例JSON字符串:

"[{\"Entry_number\":\"4\",\"Entry_date\":\"2019-01-10 18:22:55\",\"Customer_number\":\"16\",\"Entry_value\":\"13\",\"Comment\":\"Nu gaat ie t GVD doen\"},
    {\"Entry_number\":\"5\",\"Entry_date\":\"2019-01-12 14:34:23\",\"Customer_number\":\"16\",\"Entry_value\":\"10\",\"Comment\":\"TextBox\"},
    {\"Entry_number\":\"6\",\"Entry_date\":\"2019-01-12 14:34:31\",\"Customer_number\":\"16\",\"Entry_value\":\"10\",\"Comment\":\"Onrustig\"},
    {\"Entry_number\":\"7\",\"Entry_date\":\"2019-01-12 14:34:37\",\"Customer_number\":\"16\",\"Entry_value\":\"10\",\"Comment\":\"Ziek\"}]"

我希望你能帮我翻译以下内容:我正在尝试转换成以下形式:

public class SleepEntry
{
    string Entry_number;
    string Entry_date;
    string Customer_number;
    string Entry_value;
    string Comment;

    public string Entry_number1 { get => Entry_number; set => Entry_number = value; }

    public string Entry_date1 { get => Entry_date; set => Entry_date = value; }

    public string Customer_number1 { get => Customer_number; set => Customer_number = value; }

    public string Entry_value1 { get => Entry_value; set => Entry_value = value; }

    public string Comment1 { get => Comment; set => Comment = value; }
}

public class SleepData
{
    private List<SleepEntry> plants; 

    public List<SleepEntry> Plants { get => plants; set => plants = value; }
}

读取json的代码:

    public void Get_Monthly_Data()
    {


        StreamReader reader = new StreamReader(@"C:\Users\Ruben\source\repos\Health App Goede\Health App Goede\Resources\Cutstomer_ID.txt");
        Customernumber = reader.ReadLine();
        reader.Close();
        //string json = entrys();

        //convert json to series objects
        SleepData sleepdata = JsonConvert.DeserializeObject<SleepData>(entrys());

    }

    public string entrys()
    {
        string json = get.get_customer_monitoring_entry("sleep", Customernumber);

        return json;
    }

现在,我想尝试检查每个条目是否是本周的数据。然后只需从本周的每个条目中获取Entry_value,并将其显示在文本框中。非常感谢任何帮助或提示。


你尝试过使用 SleepData[] sleepdata = JsonConvert.DeserializeObject<SleepData[]>(entrys()); 吗?你展示的示例数据是一个数组([ { ... }, { ... } ])。 - Mathias
现在我想尝试检查每个条目是否属于本周。然后仅获取本周每个条目的Entry_value,并将其显示在文本框中。您能详细说明一下吗? - Anu Viswan
@Mathias,那似乎可以工作,但我如何显示所有条目的sleepdata.Entry_Value? - im_ Ruben
你可以使用for或foreach循环遍历数组。如果你只对第一个感兴趣,你也可以使用sleepdata.FirstOrDefault() - Mathias
2个回答

5

您实际上不需要那些后备字段。您可以将它们写为自动属性,使用{ get; set; }

您的JSON中有一些非常烦人的问题,即日期和数字作为字符串。因此,我建议您使用类似QuickType的工具自动生成C#模型类。

以下是结果:

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

public partial class SleepEntry
{
    [JsonProperty("Entry_number")]
    [JsonConverter(typeof(ParseStringConverter))]
    public long EntryNumber { get; set; }

    [JsonProperty("Entry_date")]
    public DateTimeOffset EntryDate { get; set; }

    [JsonProperty("Customer_number")]
    [JsonConverter(typeof(ParseStringConverter))]
    public long CustomerNumber { get; set; }

    [JsonProperty("Entry_value")]
    [JsonConverter(typeof(ParseStringConverter))]
    public long EntryValue { get; set; }

    [JsonProperty("Comment")]
    public string Comment { get; set; }
}

public partial class SleepEntry
{
    public static SleepEntry[] FromJson(string json) => JsonConvert.DeserializeObject<SleepEntry[]>(json, QuickType.Converter.Settings);
}

public static class Serialize
{
    public static string ToJson(this SleepEntry[] self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
}

internal static class Converter
{
    public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
    {
        MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
        DateParseHandling = DateParseHandling.None,
        Converters =
        {
            new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
        },
    };
}

internal class ParseStringConverter : JsonConverter
{
    public override bool CanConvert(Type t) => t == typeof(long) || t == typeof(long?);

    public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null) return null;
        var value = serializer.Deserialize<string>(reader);
        long l;
        if (Int64.TryParse(value, out l))
        {
            return l;
        }
        throw new Exception("Cannot unmarshal type long");
    }

    public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
    {
        if (untypedValue == null)
        {
            serializer.Serialize(writer, null);
            return;
        }
        var value = (long)untypedValue;
        serializer.Serialize(writer, value.ToString());
        return;
    }

    public static readonly ParseStringConverter Singleton = new ParseStringConverter();
}

使用方法:

// sleepEntries is a SleepEntry[]
var sleepEntries = SleepEntry.FromJson(jsonString);

现在我想尝试检查每个条目是否是本周的数据。然后只需获取本周每个条目的Entry_value,并将其显示在文本框中。

要确定两个日期时间是否在同一周,我们可以使用以下方法:

private bool DatesAreInTheSameWeek(DateTime date1, DateTime date2)
{
    var cal = System.Globalization.DateTimeFormatInfo.CurrentInfo.Calendar;
    var d1 = date1.Date.AddDays(-1 * (int)cal.GetDayOfWeek(date1));
    var d2 = date2.Date.AddDays(-1 * (int)cal.GetDayOfWeek(date2));

    return d1 == d2;
}

以下内容取自此问题

使用一点点LINQ就可以完成这个操作:

List<long> list = sleepEntries.Where(x => DatesAreInTheSameWeek(x.EntryDate.DateTime, DateTime.Now)).Select(x => x.EntryValue).ToList();

这似乎正是我想要做的事情。但是我该如何包含Quicktype,找不到任何可下载的dll。提前感谢! - im_ Ruben
@im_Ruben 这是一个为您生成C#代码的网站。点击答案中的链接,地址为https://quicktype.io。我答案中的代码是从QuickType复制并粘贴而来的,因此您可以将其复制并粘贴到空文件中,然后享受它。 - Sweeper
哦,是的,我检查过了,但 Quicktype.Converter.Settings 表示它在当前上下文中不存在。 - im_ Ruben
@im_Ruben 将 QuickType 更改为您所在的命名空间。它应该是 Health_App_Goede - Sweeper
1
ParseStringConverter 不在 Newtonsoft.Json.Converters 中吗? - Kiquenet
显示剩余4条评论

2

你的Json字符串是一个数组,因此你需要使用

var result = JsonConvert.DeserializeObject<IEnumerable<SleepEntry>>(str);

当 SleepEntry 被修改为:
public class SleepEntry
{
string Entry_number;
string Entry_date;
string Customer_number;
string Entry_value;
string Comment;

[JsonProperty("Entry_number")]
public string Entry_number1 { get => Entry_number; set => Entry_number = value; }
[JsonProperty("Entry_date")]
public string Entry_date1 { get => Entry_date; set => Entry_date = value; }

 [JsonProperty("Custom_number1")]
public string Customer_number1 { get => Customer_number; set => Customer_number = value; }

[JsonProperty("Entry_value")]
public string Entry_value1 { get => Entry_value; set => Entry_value = value; }

[JsonProperty("Comment")]
public string Comment1 { get => Comment; set => Comment = value; }
}

PS:您可以随时删除后台字段并使用自动属性,除非您已将其用于特定目的。

要获取当前一周中第一个条目的值。

var today = DateTime.Now;
var startOfWeek = today.AddDays((int)DateTime.Now.DayOfWeek * -1);


var value = result.Where(x=>DateTime.Parse(x.Entry_date1) > startOfWeek 
                        && DateTime.Parse(x.Entry_date1) < today.AddDays(7))
                  .Select(x=>x.Entry_value1).FirstOrDefault();

当我将变量结果转换为字符串并在文本框中显示时,它返回的是"System.Collections.Generic.List`1[Health_App_Goede.SleepEntry]",而不是JSON中的数据。 - im_ Ruben
如前所述,您的JSON是一个集合。您需要从该JSON中特别获取什么吗? - Anu Viswan
是的,我想要Entry_Value,我会在文本框中显示它,还有Entry_Date,我将用它来进行过滤。 - im_ Ruben
如果我没错的话,我认为您想要获取当前一周内日期的Entry_Value值,并在文本框中显示它。我已经更新了相应的答案。由于这一周可能会有多个条目,我选择了第一个。但是您可以根据自己的需求进行更改。如果我对您的需求的理解有误,请告诉我。 - Anu Viswan

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