簡體   English   中英

如何從文件輸入反序列化 JSON 字符串

[英]How to deserialize JSON string from file input

我正在開發一個測試應用程序來證明一些功能,我想要完成的部分工作涉及用戶填寫一個表單,一旦提交下載一個包含表單中所有值的 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; }
}

Controller

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操作,該操作采用 JSON string的字符串,甚至是IFormFile用於提交整個文件以在我將其放入 memory 后進行反序列化.

我不想將文件保存在任何地方,我試圖直接從文件中提取實際的 JSON 文本,將其反序列化回TableDemo object 並導航到填充了值的新頁面,但所有嘗試都導致要么死在我需要一個文件路徑的地方結束(我也不想將這些文件存儲在任何地方),或者在嘗試將 JSON 字符串發送到 Z594C103F2C6E04C30CAZAB059F03E 操作時得到 null 對象。

如何簡單地獲取 JSON 文件的內容,反序列化回TableDemo object 並在新頁面上顯示這些值?

System.Text.Json提供了一種簡單的方法來完成您的要求,

"提供將對象或值類型序列化為 JSON 並將 JSON 反序列化為對象或值類型的功能。 "

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

一個簡單的例子是:

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

有關此 API 的更多信息。

If you're using .NET Framework (rather than .NET Core) you'll need to install the NuGet package in the Package Manager console:

> Install-Package System.Text.Json -Version 4.7.2

好的,這是我的答案。 我瀏覽了您的代碼,並且幾乎沒有問題。 如果我需要為您解決所有問題,則需要一些時間。 但這里有一些建議,您可以將其提升到一個新的水平。

  1. 您正在嘗試使用多部分形式更新文件,但您正在嘗試獲取字符串。 您的文件包含 json 的字符串是正確的,但它仍然是一個文件。 所以我們需要處理那部分。

  2. 因此,您都在嘗試使用 JavaScript 並在視圖中顯示數據。 在我的示例中,我專注於在您的IndexDeserialized中顯示數據,而 JavaScript 部分留給另一個問題。

這是我所做的和建議的:

在您的 controller 中,刪除以下方法並將其替換為我發布的方法:

[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 object,但我認為這部分是自己的問題。

請記住,這只是示例,您可以在此基礎上做很多事情。

最終結果如下所示:

在此處輸入圖像描述

對於我所做的,我從 Microsoft 獲得了一些關於文件上傳的資料,請查看文件上傳的資源代碼示例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM