首页 > 解决方案 > 在 json 数组中搜索

问题描述

{
   "medic":[
      {
         "ace":[
            {
               "name":"lisinopril",
               "strength":"10 mg Tab",
               "dose":"1 tab",
               "route":"PO",
               "sig":"daily",
               "pillCount":"#90",
               "refills":"Refill 3"
            }
         ],
         "anti":[
            {
               "name":"nitroglycerin",
               "strength":"0.4 mg Sublingual Tab",
               "dose":"1 tab",
               "route":"SL",
               "sig":"q15min PRN",
               "pillCount":"#30",
               "refills":"Refill 1"
            }
         ],
         "anticoag":[
            {
               "name":"warfarin sodium",
               "strength":"3 mg Tab",
               "dose":"1 tab",
               "route":"PO",
               "sig":"daily",
               "pillCount":"#90",
               "refills":"Refill 3"
            }
         ],
         
      }
   ]
}
class Program
{
    static void Main(string[] args)
    {
        // ""reporttype"":""post"",
        string jsonString = @"..."; //The above json
        Console.WriteLine("Enter the Medication name in which you want to Find STRENGTH value :");
        string medicname = Console.ReadLine();
      
        var rootInstance = JsonConvert.DeserializeObject<Rootobject>(jsonString);
        }
}
var result = rootInstance.medications[0].Where(x=>x.name == medicname ).Select(t => t.strength).ToList();

但是当我运行上面的查询时,我得到以下错误:

“Medication”不包含“Where”的定义,并且找不到接受“Medication”类型的第一个参数的可访问扩展方法“Where”(您是否缺少 using 指令或程序集引用?)

我已将所有必要的名称空间添加到我的代码中。

这是我的对象类

public class Rootobject
{
    public List<Medication> medications { get; set; }
}

public class Medication
{
    public List<aceInhibitors> aceinhibitors { get ; set ; }
    public List<anti> antianginal {get; set; }
    public List<anticoag> anticoagulants {get; set; }
}

public class aceInhibitors
{
    [JsonProperty("name")]
    public string name { get; set; }
    [JsonProperty("strength")]
    public string strength { get; set; }
    [JsonProperty("dose")]
    public string dose { get; set; }
    [JsonProperty("route")]
    public string route { get; set; }
    [JsonProperty("sig")]
    public string sig { get; set; }
    [JsonProperty("pillCount")]
    public string pillCount { get; set; }
    [JsonProperty("refills")]
    public string refills { get; set; }
}

public class anti
{
    public string name { get; set; }
    public string strength { get; set; }
    public string dose { get; set; }
    public string route { get; set; }
    public string sig { get; set; }
    public string pillCount { get; set; }
    public string refills { get; set; }
}

public class anticoag
{
    public string name { get; set; }
    public string strength { get; set; }
    public string dose { get; set; }
    public string route { get; set; }
    public string sig { get; set; }
    public string pillCount { get; set; }
    public string refills { get; set; }
}

标签: c#

解决方案


适当的设计会导致数据处理和数据存储方式的分离。这样,很容易将存储的数据重用于其他处理,更容易使用测试代码对数据处理进行单元测试,您可以更改数据的存储方式,例如 CSV 文件或 XML,而无需不得不更改数据处理代码。

所以你需要一个类Medication

class Medication
{
    public string Name {get; set;}
    public string Strength {get; set;}
    public string Dose {get; set;}
    ... // etc.
}

考虑将剂量和强度更改为数值。

显然,您已将所有药物存储在某个地方。一个适当的软件设计会隐藏它的存储位置以及存储格式。您所知道的是,您可以将药物存储在其中,并在以后取回它,即使在您的程序重新启动后也是如此。这种存储通常称为Repository

class MedicationRepository
{
    public IEnumerable<Medication> ReadMedications() {...}
}

实际实施取决于您。我认为您将为此使用Nuget Package NewtonSoft Json。也许您还想要添加/更改/删除药物的方法?

考虑让 Repository 类实现IEnumerable<Medication>,甚至ICollection<Medication>,这取决于在您的情况下最有效的方法。

class MedicationRepository : IEnumerable<Medication>
{
    public IEnumerator<Medication> GetEnumerator()
    {
        return this.ReadMedications().GetEnumerator();
    }

    ...
}

现在您已经有了读取所有药物的方法,我们可以回到您的 LINQ 问题:

我需要从用户那里获取输入字符串(这是 json 中的药物名称)我需要检查输入是否与药物中的名称匹配并需要显示相应的强度值。

所以你有一个程序来读取药物名称:

public string ReadMedicationName() {...}

而你想要这个名字的所有药物的力量。

MedicationRepository medications = ...
string requestedMedicationName = this.ReadMedicationName();

string medicationStrength = medications
    .Where(medication => medication.Name == requestedMedicationName)
    .Select(medication => medication.Strength)
    .FirstOrDefault();

简而言之:从所有药物中,仅保留名称等于请求药物名称的药物。如果名称是唯一的,那么将剩下零个或一个药物。从所有剩余的药物中,仅取属性强度的值,并取第一个强度,如果根本没有具有此名称的药物,则为 null。

难不成有好几个同名的药材?在这种情况下,您想要哪一个,任何强度(= .FirstOrDefault()),所有强度(= ToList())?在后一种情况下:您如何区分具有此名称的哪种药物包含哪种强度?在这种情况下考虑Select更多的属性。

结论

通过将数据的存储以及从数据处理中获取所请求的药物名称的方式分开,可以更轻松地更改存储(更改为 XML、CSV、数据库),并且更容易使用特定的 LINQ 进行单元测试测试数据。

类似地:您隐藏了如何获得所请求药物的名称:它是 DOS 提示符吗?您是从文件中读取的吗?也许您已将其更改为 WinForms 应用程序并从文本框或 ComboBox 中读取它。因为您分开了,LINQ 不必更改,并且可以在多个平台上重复使用。


推荐阅读