【问题标题】:How to deserialize JSON string from file input如何从文件输入反序列化 JSON 字符串
【发布时间】:2020-09-23 22:06:40
【问题描述】:

我正在开发一个测试应用程序来证明一些功能,我想要完成的部分工作涉及用户填写表单,一旦提交,就会下载包含表单中所有值的 JSON 文件。在那里,用户然后将该 JSON 文件发送给另一方,该方将获取该文件并使用它来填写表单上的其他信息,同时保留原始用户的选择。

这是我到目前为止所得到的。

数据模型

public class TableDemo
{
    public List<Location> Locations { get; set; }
    public List<User> Users { get; set; }

    public TableDemo()
    {
        Locations = new List<Location>();
        Locations.Add(new Location());

        Users = new List<User>();
        Users.Add(new User());
    }
}

public class Location
{
    [Required]
    public string Street { get; set; }
    [Required]
    public string City { get; set; }
    [Required]
    public string State { get; set; }
    [Required]
    public string Zip { get; set; }
}

public class User
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string PhoneNumber { get; set; }
}

控制器

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;

    public HomeController(ILogger<HomeController> logger)
    {
        _logger = logger;
    }

    public IActionResult Index()
    {
        TableDemo model = new TableDemo();
        return View(model);
    }

    // This is where the user fills out the original form which downloads to their machine as a JSON file.
    [HttpPost]
    public IActionResult Index(TableDemo model)
    {
        string jsonString;
        var options = new JsonSerializerOptions
        {
            WriteIndented = true
        };
        jsonString = JsonSerializer.Serialize(model, options);
        byte[] jsonFileArray = Encoding.ASCII.GetBytes(jsonString);
        return File(jsonFileArray, "application/json", "testJson.json");
    }

    // Where the second user inputs the file from the first user
    [HttpGet]
    public IActionResult ImportForm()
    {
        return View();
    }

    // the jsonString argument is always null here
    [HttpPost]
    public IActionResult ImportForm(string jsonString)
    {
        TableDemo model = JsonSerializer.Deserialize<TableDemo>(jsonString);
        return View("IndexDeserialized", model);
    }
}

查看(ImportForm.cshtml)

@section Scripts{
<script>
    function showFile(input) {
        let file = input.files[0];

        let reader = new FileReader();
        reader.readAsText(file);

        reader.onload = () => {
            console.log(reader.result);
            let jsonContent = $('#jsonContent');
            jsonContent.append(reader.result);
        };

        reader.onerror = function () {
            console.log(reader.error);
        };
    };
</script>
}

<body>
<form name="form" method="post" enctype="multipart/form-data">
    <div class="form-group">
        <input type="file" class="form-control" name="file" onchange="readDocument(this)" />
    </div>
    <div id="jsonContent">

    </div>

    <div class="form-group">
        <button type="submit" class="btn btn-primary">Submit</button>
    </div>
</form>
</body>

我从初始视图生成的 JSON 文件的内容

{
  "Locations": [
    {
      "Street": "12345 Test Drive",
      "City": "Chicago",
      "State": "IL",
      "Zip": "55555"
    },
    {
      "Street": "12345 Test Drive",
      "City": "ABC",
      "State": "IL",
      "Zip": "60441"
    },
    {
      "Street": "1234",
      "City": "asdasd",
      "State": "asdasd",
      "Zip": "asdasd"
    }
  ],
  "Users": [
    {
      "FirstName": "asdas",
      "LastName": "dasdsa",
      "PhoneNumber": "dasd"
    },
    {
      "FirstName": "sadasd",
      "LastName": "dsadas",
      "PhoneNumber": "asdasd"
    }
  ]
}

所以从这里我有点迷路了。我尝试了几种方法,在这些方法中我提交文件并为ImportForm 设置相应的HttpPost 操作,该操作将string 用于JSON 字符串,甚至IFormFile 用于仅提交要反序列化的整个文件一旦我记住了它。

我不想将文件保存在任何地方,我试图直接从文件中提取实际的 JSON 文本,将其反序列化回 TableDemo 对象并导航到填充值的新页面,但所有尝试导致我需要有文件路径的死胡同(我不想再将这些文件存储在任何地方),或者在尝试将 JSON 字符串发送到控制器操作时得到空对象。

如何简单地获取 JSON 文件的内容,反序列化回 TableDemo 对象并在新页面上显示这些值?

【问题讨论】:

  • @maytham-ɯɐɥʇʎɐɯ 所以说我只有一个简单的@model string 就我的观点而言,我如何能够将脚本中收集的字符串值从 JS FileReader 发送到控制器?
  • @maytham-ɯɐɥʇʎɐɯ 有时间的时候回答会很好。如果可以的话,显示这两种方法。我这样做是作为一个学习练习,我刚刚在这里被难住了,所以绝对感谢任何帮助。
  • yaa rignt 现在晚上 11:00 我的位置,所以我将开始 1-2 小时有其他事情要做。但希望在睡前,如果我的大脑继续工作的话。如果我稍后有问题,请保持联系。
  • 你上传的那个json是你问题中的那个吗?
  • 是的,它是从应用程序中其他视图的虚拟输入生成的 JSON 文件。我排除了这一点,以使问题的范围更加集中,因为该部分已经有效,并且问题出现在我获得文件之后。

标签: javascript c# json asp.net-core


【解决方案1】:

好的,这是我的答案。我浏览了您的代码,并且几乎没有问题。如果我需要为您解决所有问题,则需要一些时间。但这里有一些建议,您可以将其提升到一个新的水平。

  1. 您正在尝试使用多部分格式更新文件,但您正在尝试获取字符串。您的文件包含json字符串是正确的,但它仍然是一个文件。所以我们需要处理那部分。

  2. 所以你们都在尝试使用 JavaScript 并在视图中显示数据。在我的示例中,我专注于在您的 IndexDeserialized 中显示数据,而 JavaScript 部分留待另一个问题。

这是我所做的和建议的:

在您的控制器中,删除以下方法并将其替换为我发布的方法:

[HttpPost]
public IActionResult ImportForm(string jsonString)
{
    TableDemo model = JsonSerializer.Deserialize<TableDemo>(jsonString);
    return View("IndexDeserialized", model);
}

新方法,这只是一个简单的例子,可以读取你上传的文件并将结果返回到同一页面。

[HttpPost]
public async Task<IActionResult> ImportFormOnPost()
{
    string jsonString = string.Empty;

    if (HttpContext.Request.Form.Files[0] != null)
    {
        var file = HttpContext.Request.Form.Files[0];
        await using (MemoryStream ms = new MemoryStream())
        {
            await file.CopyToAsync(ms);
            jsonString = Encoding.UTF8.GetString(ms.ToArray());
        }
    }


    TableDemo model = JsonSerializer.Deserialize<TableDemo>(jsonString);
    return View("IndexDeserialized", model);
}

在您的 ImportForm 中,您缺少操作,在这种情况下,我们将发布到 ImportFormOnPost 方法:

<form name="form" method="post" enctype="multipart/form-data" action="ImportFormOnPost">
    <div class="form-group">
        <input type="file" class="form-control" name="file" />
    </div>
    <div id="jsonContent">

    </div>

    <div class="form-group">
        <button type="submit" class="btn btn-primary">Submit</button>
    </div>

    <div style="margin-top:15px">
        <output form="uploadForm" name="result"></output>
    </div>
</form>

最后,我们将在IndexDeserialized 中展示您的数据:

@model FileUploaderApp.Models.TableDemo
<p>Number for locations: @Model?.Locations?.Count</p>

@if (Model != null)
{
    foreach (var user in @Model.Users)
    {
        <p>@user.FirstName @user.LastName</p>
    }
}

在前端使用 JavaScript 时,可以将数据显示为 JSON 对象,但我认为这部分是它自己的问题。

请记住,这只是示例,您可以在此基础上做很多事情。

最终的结果是这样的:

对于我所做的,我从 Microsoft 获得了一些关于 file uploading 的信息,请查看此文件上传的 resource 代码示例。

【讨论】:

  • 嘿,谢谢。这行得通。让我失望的一件事是 IFormFile myFile 以 null 的形式出现。如果它没有在代码中使用,它甚至需要作为参数吗?相反,您只需从 HttpContext.Request 获取文件。
  • 我很高兴它对你有用。我的错误是我使用了不同的示例,其中一个是 IFormFile,所以我更新了代码,我更新了代码。但在概念上是一样的。
【解决方案2】:

System.Text.Json 提供了一种简单的方式来满足您的要求,

"提供将对象或值类型序列化为 JSON 并将 JSON 反序列化为对象或值类型的功能。"

使用JsonSerializer API,您可以使用返回stringSerialize() 和返回objectDeserialize()

一个简单的例子是:

TableDemo table = System.Text.Json.JsonSerializer.Deserialize(jsonInputString, typeof(TableDemo), options);

More 在此 API 上。

如果您使用的是 .NET Framework(而不是 .NET Core),则需要在包管理器控制台中安装 NuGet 包:

&gt; Install-Package System.Text.Json -Version 4.7.2

【讨论】:

  • 您好,谢谢您的回答。我已经阅读了该文档,我遇到的问题是,当我尝试使用接受 JSON 字符串的控制器操作时,它始终为空。我不知道我只是犯了一个愚蠢的错误还是什么,但我无法将 JSON 字符串发送到控制器。我将使用我尝试处理的控制器操作之一来编辑问题。
猜你喜欢
  • 2013-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-23
  • 1970-01-01
  • 1970-01-01
  • 2021-09-02
  • 1970-01-01
相关资源
最近更新 更多