Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 反序列化C中的开放街道地图JSON#_C#_Json_Json.net_Openstreetmap_Json Deserialization - Fatal编程技术网

C# 反序列化C中的开放街道地图JSON#

C# 反序列化C中的开放街道地图JSON#,c#,json,json.net,openstreetmap,json-deserialization,C#,Json,Json.net,Openstreetmap,Json Deserialization,如果我有这个JSON,其中有一个带有标签version,generator,om3s和元素的头元素可以是节点或方式类型,并且相关的JSON键根据类型而不同。我尝试使用将每个元素类型转换为C#类 JSON示例: [ { "version": 0.6, "generator": "Overpass API 0.7.55.7 8b86ff77", "osm3s": { "timestamp_osm_base": "2019-05-21T18:03:02Z",

如果我有这个JSON,其中有一个带有标签
version
generator
om3s
元素的头<代码>元素
可以是
节点
方式
类型,并且相关的JSON键根据类型而不同。我尝试使用将每个元素类型转换为C#类

JSON示例:

[
  {
    "version": 0.6,
    "generator": "Overpass API 0.7.55.7 8b86ff77",
    "osm3s": {
      "timestamp_osm_base": "2019-05-21T18:03:02Z",
      "copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL."
    },
    "elements": [
      {
        "type": "node",
        "id": 4949106384,
        "lat": 32.2686857,
        "lon": -107.738218,
        "tags": {
          "highway": "turning_circle"
        }
      },
      {
        "type": "way",
        "id": 14527404,
        "nodes": [
          142882281,
          3048075541,
          1598998260
        ],
        "tags": {
          "highway": "residential",
          "name": "West Apple Street",
          "tiger:cfcc": "A41",
          "tiger:county": "Luna, NM",
          "tiger:name_base": "Apple",
          "tiger:name_direction_prefix": "W",
          "tiger:name_type": "St",
          "tiger:reviewed": "no"
        }
      }
    ]
  }
]
我正在尝试使用以下方法对其进行反序列化:

var json = JsonConvert.DeserializeObject<OSMdata>(jsonText);
返回:

Unhandled Exception: System.ArgumentNullException: Value cannot be null.
   at System.RuntimeType.MakeGenericType(Type[] instantiation)
   at JsonSubTypes.JsonSubtypes.CreateCompatibleList(Type targetContainerType, Type elementType)
   at JsonSubTypes.JsonSubtypes.ReadArray(JsonReader reader, Type targetType, JsonSerializer serializer)
   at JsonSubTypes.JsonSubtypes.ReadJson(JsonReader reader, Type objectType, JsonSerializer serializer)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
   at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
   at newapp.Program.Main(String[] args) in C:\Users\RDCRLDDH\source\repos\newapp\newapp\Program.cs:line 23
虽然我不理解这一错误,正在寻找解决方案,但我想澄清以下几个问题:

问题 我是否正确构造了类
OSMdata
?我认为我正确地遵循了这些示例,但不确定是否正确地将类
节点
边缘
分配给父类
OSMdata


反序列化程序如何知道将标记
“tiger:cfcc”
分配给
EdgeTags
中的
cfcc
属性?

我不知道如何直接从JSON反序列化,但是找到了一个合适的解决方法,可以将JSON转换为
JArray
,迭代每个元素,并转换为由节点和边组成的C#类

使用class
元素

    [JsonConverter(typeof(JsonSubtypes), "type")]
    [JsonSubtypes.KnownSubType(typeof(Element.Node), "node")]
    [JsonSubtypes.KnownSubType(typeof(Element.Edge), "way")]

    public class Element
    {
        public class Node : Element

        {
            public string type { get; } = "node";
            public long id { get; set; }
            public float lat { get; set; }
            public float lon { get; set; }
            public NodeTags tags { get; set; }
        }

    public class NodeTags : Node
    {
        public string highway { get; set; }
        public string _ref { get; set; }
    }

    public class Edge : Element
    {
        public string type { get; } = "way";
        public long id { get; set; }
        public long[] nodes { get; set; }
        public EdgeTags tags { get; set; }
    }

    public class EdgeTags : Edge
    {
        [JsonProperty("highway")]
        public string Highway { get; set; }

        [JsonProperty("name")]
        public string Name { get; set; }


        [JsonProperty("tiger:cfcc")]
        public string cfcc { get; set; }

        [JsonProperty("tiger:county")]
        public string County { get; set; }

        [JsonProperty("oneway")]
        public string Oneway { get; set; }
    }
您可以使用以下方法解析thje json:

JArray jsonSearch = JArray.Parse(jsonText);
然后,可以使用以下方法创建由每个元素组成的列表:

IList<JToken> results = jsonSearch[0]["elements"].Children().ToList();
在我提出的问题中,第二个问题仍然相关

在类中创建属性名称之前,可以使用
JsonProperty
将名称无效的属性分配给C#类

[JsonProperty("tiger:cfcc")]
public string cfcc { get; set; }

感谢@dbc和其他有用的评论为我指明了正确的方向

按如下方式声明您的类:


//不再抽象
公共类OSMdata
{
公共浮点版本{get;set;}
公共字符串生成器{get;set;}
公共Osm3s Osm3s{get;set;}
//对于数组或集合,此处必须显示此行
[JsonConverter(类型化(JsonSubtypes),“类型”)]
公共元素[]元素{get;set;}
}
//不需要从OSMData继承
公共类Osm3s
{
public DateTime timestamp_osm_base{get;set;}
公共字符串版权{get;set;}
}
[JsonConverter(类型化(JsonSubtypes),“类型”)]
[JsonSubtypes.KnownSubType(typeof(Node),“Node”)]
[JsonSubtypes.KnownSubType(typeof(Edge),“way”)]
公共抽象类元素:OSMdata
{
公共抽象字符串类型{get;}
}
公共类节点:元素
{
公共重写字符串类型{get;}=“node”;
公共长id{get;set;}
公共浮点lat{get;set;}
公共浮点lon{get;set;}
公共节点标记{get;set;}
}
公共类节点
{
公共字符串公路{get;set;}
公共字符串_ref{get;set;}
}
公共类边缘:元素
{
公共重写字符串类型{get;}=“way”;
公共长id{get;set;}
公共长[]节点{get;set;}
公共EdgeTags标记{get;set;}
}
公共类边
{
公共字符串公路{get;set;}
公共字符串名称{get;set;}
公共字符串cfcc{get;set;}
公共字符串country{get;set;}
单向公共字符串{get;set;}
}
并反序列化为:

var json=JsonConvert.DeserializeObject(jsonText);

请参阅运行示例:

另一种解决方案是添加一个
NodeOrEdge
类,并在它们之间编写自定义转换。让库处理丢失的键。您可以使用多态
元素
数组对模型进行反序列化,而不是加载到某个巨大的
动态
对象然后手动反序列化。有关如何查看,或@dbc感谢阅读!无论何时使用
dynamic
都要时刻思考,最有可能的是way@dubbbdan-不客气。这些回答了你的问题吗?如果没有,则始终可以使用
JToken.ToObject()
JToken.ToObject()
,如和所示。希望您的问题能通过以下问题之一得到回答。将
EdgeTags
Edge
(即
公共类EdgeTags:Edge
)关联是否合适?
var element_list = new List<Element>();

foreach (JObject element in results)
{
    Element myelement = element.ToObject<Element>();
    element_list.Add(myelement);
}
[JsonProperty("tiger:cfcc")]
public string cfcc { get; set; }