【问题标题】:Is there a way to extract contents of a JSON string using LINQ有没有办法使用 LINQ 提取 JSON 字符串的内容
【发布时间】:2019-09-01 08:35:13
【问题描述】:

我有这个代码:

var jsonResponse = response.Content.ReadAsStringAsync().Result;
            List<TranslationResult> a  = JsonConvert.DeserializeObject< List<TranslationResult>>(jsonResponse);
var t0 = (a[0] != null) ? a[0] : null;
var t1 = (t0 != null) ? t0.Translations[0] : null;
var t2 = (t1 != null) ? t1.DisplayTarget : null;
var p2 = (t1 != null) ? t1.PosTag : null;

public class TranslationResult
{
    public string DisplaySource { get; set; }
    public Translation[] Translations { get; set; }
}

public class Translation
{
    public string DisplayTarget { get; set; }
    public string PosTag { get; set; }
}

我用于所有空测试的代码看起来很乱,我想清理一下。任何人都可以提出一种我可以做到这一点的方法,或者如果可能的话,可以提出一种使用 LINQ 的方法。请注意,我只需要 DisplayTarget 和 PosTag 详细信息。

【问题讨论】:

标签: c# json linq


【解决方案1】:

您只能使用 LINQ 来获取翻译结果和其中的翻译。你仍然需要解压DisplayTargetPosTag

List<TranslationResult> a = JsonConvert.DeserializeObject<List<TranslationResult>>(jsonResponse);
var firstTranslation = a.FirstOrDefault()?.Translations?.FirstOrDefault();
var displayTarget = firstTranslation?.DisplayTarget;
var posTag = firstTranslation?.PosTag;

此外,您可以使用 C# 7.0 元组一次性解压缩多个值。

List<TranslationResult> a = JsonConvert.DeserializeObject<List<TranslationResult>>(jsonResponse);
var firstTranslation = a.FirstOrDefault()?.Translations?.FirstOrDefault();
var (displayTarget, posTag) = (firstTranslation?.DisplayTarget, firstTranslation?.PosTag);

如果您想使用所有值,而不仅仅是像您的示例中那样,您可以使用 LINQ,如下所示:

List<TranslationResult> results = JsonConvert.DeserializeObject<List<TranslationResult>>(jsonResponse);
var translations = (results ?? Enumerable.Empty<TranslationResult>())
            .Select(x => x.Translations)
            .Where(x => x != null)
            .SelectMany(x => x)
            .Where(x => x != null)
            .Select(x => (x.DisplayTarget, x.PosTag));
foreach (var (displayTarget, posTag) in translations)
{
    // do something with displayTarget and posTag
}

【讨论】:

  • 这仅从具有 n 个结果的列表中返回 1 个结果,并丢弃两个集合(内部和外部)的剩余 n-1 个结果。
  • @BionicCode 谢谢!对其展开。对这个问题感到困惑,对我来说,似乎只需要第一个值。
【解决方案2】:

这是一个使用 Linq 和命名元组的示例:

List<TranslationResult> a = JsonConvert.DeserializeObject<List<TranslationResult>>(jsonResponse);

IEnumerable<(string DisplayTarget, string PosTag)> tuples = 
  a.Where(t0 => t0?.Translations ?? false)
    .SelectMany(
      t0 => t0.Translations.Select(
        t1 => (DisplayTarget: t1?.DisplayTarget ?? string.Empty, PosTag: t1?.PosTag ?? string.Empty)));

// Iterate over the result of named tuples
foreach ((string DisplayTarget, string PosTag) tuple : tuples)
{
  // Values are string.Empty when they returned null from deserialization
  var displayTarget = tuple.DisplayTarget;
  var posTag = tuple.PosTag;
}

【讨论】:

    【解决方案3】:
    var t0 = (a[0] != null) ? a[0] : null;
    

    这个可以改成

    var t0 = a[0];
    

    因为结果是一样的。还有

    var t1 = (t0 != null) ? t0.Translations[0] : null;
    var t2 = (t1 != null) ? t1.DisplayTarget : null;
    var p2 = (t1 != null) ? t1.PosTag : null;
    

    可以改成

    var t1 = t0?.Translations[0];
    var t2 = t1?.DisplayTarget;
    var p2 = t1?.PosTag;
    

    使用null condition operator 是“如果不为空,则返回,否则返回空”检查的简写形式。

    【讨论】:

      【解决方案4】:

      query 可能更容易:

       string PosTag = (string)JToken.Parse(jsonResponse).SelectToken("$..PosTag");
      

      【讨论】:

        猜你喜欢
        • 2021-05-15
        • 2022-12-11
        • 2022-01-14
        • 2021-10-04
        • 1970-01-01
        • 2021-09-06
        • 1970-01-01
        • 2017-12-09
        • 2020-04-17
        相关资源
        最近更新 更多