等效于.net5中的jarray.fromobject()?

发布于 2025-01-23 08:57:16 字数 3087 浏览 0 评论 0 原文

我们有一个项目,该项目使用.net 5中使用 System.Text.json 而不是 newtonsoft jobign 。使用newtonsoft,替换动态JSON数据非常容易如下:如下所示:

siteDataObject["student"] = JArray.FromObject(studentservice.GetStudents());

sustomeService.getStudents()为返回列表如下所示,

internal class Student {
    public int Id { get; set; }
    public string Name { get; set; }
    public string ContactPhone { get; set; }

    public IEnumerable<MedicalRecord> MedicalRecords { get; set; }
}

internal class MedicalRecord {
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime RecordDate { get; set; }
    public IEnumerable<DiseaseLog> DiseaseLogs{ get; set; }
}

internal class DiseaseLog {
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime LogDate { get; set; }
}

但在system.text.json中,

foreach (var element in doc.RootElement.EnumerateObject()) {
    if (element.Name == "student") {
        writer.WritePropertyName(element.Name);
    
    }
    else {
        element.WriteTo(writer);
    }
}

我不知道如何转换 list&lt; student&lt; ; 进入JSON数组数据时,当学生类具有许多内部包含多收集的属性时。

Can anyone advise how to convert it ?

为了澄清,我需要为此提出完整的代码,我有一个动态的JSON字符串,想替换元素:学生将代码替换为新的记录,

var dynamicJson = @"{'roomid':1,'roomcode':'Code001','students':[1],'contentdata':'say hello','footerdata':'cookie policy'}";
using MemoryStream stream = new MemoryStream();
using Utf8JsonWriter writer = new Utf8JsonWriter(stream);
using var dynamicDocument = JsonDocument.Parse(dynamicJson);
writer.WriteStartObject();
foreach (var element in dynamicDocument.RootElement.EnumerateObject())
{
    if (element.Name == "students")
    {
        // unknown how to modify the student record into array
    }
    else
        element.WriteTo(writer);
}
writer.WriteEndObject();
stream.Flush();
var modifyJson = Encoding.UTF8.GetString(stream.ToArray());

如果学生元素是字符串,我将知道如何修改学生的价值,但是我don't know how to modify it into array, by using simple code.作为学生在里面有多个课程。

我的预期结果应该是

{
    "roomid": 1,
    "roomcode": "Code001",
    "students": [
        {
            "id": 1,
            "Name": "Wilson",
            "ContactPhone": "123-122-3311",
            "MedicalRecords": [
                {
                    "id": 101,
                    "Name ": "Medial record 101011",
                    "RecordDate": "2021-12-31",
                    "DiseaseLogs": [
                        {
                            "id": 18211,
                            "Name ": "Patient Log 19292",
                            "LogDate": "2020-1-31"
                        },
                        {
                            "id": 18212,
                            "Name ": "Patient Log 2911w",
                            "LogDate": "2020-3-31"
                        }
                    ]
                }
            ]
        }
    ],
    "contentdata": "say hello",
    "footerdata": "cookie policy"
}

We have a project which using System.Text.Json in .NET 5 instead of Newtonsoft JObject. Using Newtonsoft, it is pretty easy to replace dynamic JSON data e.g. as shown below:

siteDataObject["student"] = JArray.FromObject(studentservice.GetStudents());

When studentservice.GetStudents() is return List as below structure

internal class Student {
    public int Id { get; set; }
    public string Name { get; set; }
    public string ContactPhone { get; set; }

    public IEnumerable<MedicalRecord> MedicalRecords { get; set; }
}

internal class MedicalRecord {
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime RecordDate { get; set; }
    public IEnumerable<DiseaseLog> DiseaseLogs{ get; set; }
}

internal class DiseaseLog {
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime LogDate { get; set; }
}

but in System.Text.Json

foreach (var element in doc.RootElement.EnumerateObject()) {
    if (element.Name == "student") {
        writer.WritePropertyName(element.Name);
    
    }
    else {
        element.WriteTo(writer);
    }
}

I don't know how to convert List<student> into JSON array data, when student class have many properties with multi collection inside.

Can anyone advise how to convert it ?

To clarify, I need to propose the full code for this, I have a dynamic json string and want to replace element : students into new record, the code will be

var dynamicJson = @"{'roomid':1,'roomcode':'Code001','students':[1],'contentdata':'say hello','footerdata':'cookie policy'}";
using MemoryStream stream = new MemoryStream();
using Utf8JsonWriter writer = new Utf8JsonWriter(stream);
using var dynamicDocument = JsonDocument.Parse(dynamicJson);
writer.WriteStartObject();
foreach (var element in dynamicDocument.RootElement.EnumerateObject())
{
    if (element.Name == "students")
    {
        // unknown how to modify the student record into array
    }
    else
        element.WriteTo(writer);
}
writer.WriteEndObject();
stream.Flush();
var modifyJson = Encoding.UTF8.GetString(stream.ToArray());

I know how to modify student value , if student element is string, but I don't know how to modify it into array, by using simple code. As student have multi class inside.

My expected result should be

{
    "roomid": 1,
    "roomcode": "Code001",
    "students": [
        {
            "id": 1,
            "Name": "Wilson",
            "ContactPhone": "123-122-3311",
            "MedicalRecords": [
                {
                    "id": 101,
                    "Name ": "Medial record 101011",
                    "RecordDate": "2021-12-31",
                    "DiseaseLogs": [
                        {
                            "id": 18211,
                            "Name ": "Patient Log 19292",
                            "LogDate": "2020-1-31"
                        },
                        {
                            "id": 18212,
                            "Name ": "Patient Log 2911w",
                            "LogDate": "2020-3-31"
                        }
                    ]
                }
            ]
        }
    ],
    "contentdata": "say hello",
    "footerdata": "cookie policy"
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

似最初 2025-01-30 08:57:16

在.NET 5中,没有内置到System.Text.json中的可修改JSON文档对象模型。 是仅读取的, system.text.json.nodes 仅在.NET 6中引入。因此,最简单的方法是供应,修改和重新序列化的自由形式JSON <强>在.NET 5中是对某些部分数据模型进行序列化,并将未知值绑定到字典中。

如果您不关心根级的属性顺序,则可以使用公共对象学生{get;放; } 属性,并将其余元素绑定到 jsonextensiondata 溢出字典:

public class RootObject
{
    public object students { get; set; }

    [System.Text.Json.Serialization.JsonExtensionDataAttribute]
    public IDictionary<string, object> ExtensionData { get; set; }
}

然后deleialize,修改和重新序列化如下:

var students = new List<Student> { /* Initialize these as required... */ };

var dynamicJson = @"{""roomid"":1,""roomcode"":""Code001"",""students"":[1],""contentdata"":""say hello"",""footerdata"":""cookie policy""}";

var root = JsonSerializer.Deserialize<RootObject>(dynamicJson);

root.students = students;

var modifyJson = JsonSerializer.Serialize(root, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, WriteIndented = true });

哪些结果

{
  "students": [
    {
      "id": 1,
      "name": "Wilson",
      "contactPhone": "123-122-3311",
      "medicalRecords": [
        {
          "id": 101,
          "name": "Medial record 101011",
          "recordDate": "2021-12-31T00:00:00",
          "diseaseLogs": [
            {
              "id": 18211,
              "name": "Patient Log 19292",
              "logDate": "2020-01-31T00:00:00"
            },
            {
              "id": 18212,
              "name": "Patient Log 2911w",
              "logDate": "2020-03-31T00:00:00"
            }
          ]
        }
      ]
    }
  ],
  "roomid": 1,
  "roomcode": "Code001",
  "contentdata": "say hello",
  "footerdata": "cookie policy"
}

必须在 susidenite 属性中声明为属性为<代码>对象因为输入JSON已经具有包含单个整数值的数组。将其宣布为公共列表&lt; student&gt;学生{get;放; } 在最初加载JSON时会导致避难所。

演示小提琴#1 在这里

如果您确实关心根级的属性顺序,则可以对 orderedDictionary (旧订单 - 订单 - 列出的非基因词典。 “ 值,然后重新序列化:

var students = new List<Student> { /* Initialize these as required... */ };

var dynamicJson = @"{""roomid"":1,""roomcode"":""Code001"",""students"":[1],""contentdata"":""say hello"",""footerdata"":""cookie policy""}";

var root = JsonSerializer.Deserialize<OrderedDictionary>(dynamicJson);

root["students"] = students;

var modifyJson = JsonSerializer.Serialize(root, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, WriteIndented = true });

将导致

{
  "roomid": 1,
  "roomcode": "Code001",
  "students": [
    {
      "id": 1,
      "name": "Wilson",
      "contactPhone": "123-122-3311",
      "medicalRecords": [
        {
          "id": 101,
          "name": "Medial record 101011",
          "recordDate": "2021-12-31T00:00:00",
          "diseaseLogs": [
            {
              "id": 18211,
              "name": "Patient Log 19292",
              "logDate": "2020-01-31T00:00:00"
            },
            {
              "id": 18212,
              "name": "Patient Log 2911w",
              "logDate": "2020-03-31T00:00:00"
            }
          ]
        }
      ]
    }
  ],
  "contentdata": "say hello",
  "footerdata": "cookie policy"
}

演示小提琴#2 在这里


在.net 6中,通过使用 system.text.json.nodes 可编辑的JSON文档对象模型:

var dynamicJson = @"{""roomid"":1,""roomcode"":""Code001"",""students"":[1],""contentdata"":""say hello"",""footerdata"":""cookie policy""}";

var nodes = JsonSerializer.Deserialize<JsonObject>(dynamicJson);

nodes["students"] = JsonSerializer.SerializeToNode(students, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });

var modifyJson = nodes.ToString();

但是在.NET 5中,这是不可能的。演示小提琴#3 在这里

In .NET 5 there is no modifiable JSON Document Object Model built into to System.Text.Json. JsonDocument is read-only, and System.Text.Json.Nodes was only introduced in .NET 6. Thus, the easiest way to deserialize, modify and re-serialize free-form JSON in .NET 5 is to deserialize to some partial data model, with unknown values bound into a dictionary.

If you do not care about the order of properties at the root level, you could deserialize to a model with a public object students { get; set; } property, and bind the remaining elements to a JsonExtensionData overflow dictionary:

public class RootObject
{
    public object students { get; set; }

    [System.Text.Json.Serialization.JsonExtensionDataAttribute]
    public IDictionary<string, object> ExtensionData { get; set; }
}

Then deserialize, modify and re-serialize as follows:

var students = new List<Student> { /* Initialize these as required... */ };

var dynamicJson = @"{""roomid"":1,""roomcode"":""Code001"",""students"":[1],""contentdata"":""say hello"",""footerdata"":""cookie policy""}";

var root = JsonSerializer.Deserialize<RootObject>(dynamicJson);

root.students = students;

var modifyJson = JsonSerializer.Serialize(root, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, WriteIndented = true });

Which results in

{
  "students": [
    {
      "id": 1,
      "name": "Wilson",
      "contactPhone": "123-122-3311",
      "medicalRecords": [
        {
          "id": 101,
          "name": "Medial record 101011",
          "recordDate": "2021-12-31T00:00:00",
          "diseaseLogs": [
            {
              "id": 18211,
              "name": "Patient Log 19292",
              "logDate": "2020-01-31T00:00:00"
            },
            {
              "id": 18212,
              "name": "Patient Log 2911w",
              "logDate": "2020-03-31T00:00:00"
            }
          ]
        }
      ]
    }
  ],
  "roomid": 1,
  "roomcode": "Code001",
  "contentdata": "say hello",
  "footerdata": "cookie policy"
}

the students property must be declared as object because the input JSON already has an array containing a single integer value; declaring it as public List<Student> students { get; set; } would result in a deserialization when initially loading the JSON.

Demo fiddle #1 here.

If you do care about the order of properties at the root level, you could deserialize to an OrderedDictionary (an old order-preserving non-generic dictionary dating from .NET Framework 2.0 which is still around and supported), overwrite the "students" value, and re-serialize:

var students = new List<Student> { /* Initialize these as required... */ };

var dynamicJson = @"{""roomid"":1,""roomcode"":""Code001"",""students"":[1],""contentdata"":""say hello"",""footerdata"":""cookie policy""}";

var root = JsonSerializer.Deserialize<OrderedDictionary>(dynamicJson);

root["students"] = students;

var modifyJson = JsonSerializer.Serialize(root, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, WriteIndented = true });

Which results in

{
  "roomid": 1,
  "roomcode": "Code001",
  "students": [
    {
      "id": 1,
      "name": "Wilson",
      "contactPhone": "123-122-3311",
      "medicalRecords": [
        {
          "id": 101,
          "name": "Medial record 101011",
          "recordDate": "2021-12-31T00:00:00",
          "diseaseLogs": [
            {
              "id": 18211,
              "name": "Patient Log 19292",
              "logDate": "2020-01-31T00:00:00"
            },
            {
              "id": 18212,
              "name": "Patient Log 2911w",
              "logDate": "2020-03-31T00:00:00"
            }
          ]
        }
      ]
    }
  ],
  "contentdata": "say hello",
  "footerdata": "cookie policy"
}

Demo fiddle #2 here.


In .NET 6 this all becomes easier through use of the System.Text.Json.Nodes editable JSON Document Object Model:

var dynamicJson = @"{""roomid"":1,""roomcode"":""Code001"",""students"":[1],""contentdata"":""say hello"",""footerdata"":""cookie policy""}";

var nodes = JsonSerializer.Deserialize<JsonObject>(dynamicJson);

nodes["students"] = JsonSerializer.SerializeToNode(students, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });

var modifyJson = nodes.ToString();

But in .NET 5 this is not possible. Demo fiddle #3 here.

忘你却要生生世世 2025-01-30 08:57:16

我认为这就是您想要的(数组或单个嵌套对象):

var student = new Student()
{
    Name = "Student",
    ContactPhone = "contact",
    Id = 1,
    MedicalRecords = new List<MedicalRecord>()
    {
        new MedicalRecord()
        {
            Name = "Medical Record 1",
            RecordDate= DateTime.Now ,
            Id = 1 ,
            MedicalRecords = new List<DiseaseLog>()
            {
                new DiseaseLog(){ Name = "some disease" ,
                    LogDate = DateTime.Now, Id =1  }
            }
        }
    }
};

var data = System.Text.Json.JsonSerializer.Serialize(student);
Console.WriteLine(data);


var list = new List<Student>();
list.Add(student);

var arrayData = System.Text.Json.JsonSerializer.Serialize(list);

Console.WriteLine(arrayData);

I think this is what you want (array or single nested object):

var student = new Student()
{
    Name = "Student",
    ContactPhone = "contact",
    Id = 1,
    MedicalRecords = new List<MedicalRecord>()
    {
        new MedicalRecord()
        {
            Name = "Medical Record 1",
            RecordDate= DateTime.Now ,
            Id = 1 ,
            MedicalRecords = new List<DiseaseLog>()
            {
                new DiseaseLog(){ Name = "some disease" ,
                    LogDate = DateTime.Now, Id =1  }
            }
        }
    }
};

var data = System.Text.Json.JsonSerializer.Serialize(student);
Console.WriteLine(data);


var list = new List<Student>();
list.Add(student);

var arrayData = System.Text.Json.JsonSerializer.Serialize(list);

Console.WriteLine(arrayData);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文