反序列化包含一个或多个JSON对象的存档的文本文件

时间:2012-03-04 00:29:09

标签: c# json json.net

我正在使用Json.net反序列化并使用一个包含一到几千个JSON格式的Twitter推文的文件(将其视为单个JSON对象的大型文本文件存档)。为了简化这篇文章和插图的目的,我将每个Tweet的JSON减少到只有四行,但它们实际上有几十个属性。

我没有在JSON中创建包含推文的文件 - 它来自我无法控制或无法访问的数据库中的这种形式。以下是包含一条推文的文件示例:

{
    "created_at": "Thu Mar 20 02:59:35 +0000 2009",
    "text": "meet you later tonight"
}

以下是包含两条推文的文件示例:

{
    "created_at": "Thu Mar 21 02:59:35 +0000 2010",
    "text": "meet you later"
}
{
    "created_at": "Thu Mar 22 02:59:35 +0000 2010",
    "text": "see you tonight"
}

问题:当文件可能包含一个或多个JSON对象时,如何将文件反序列化为推文对象列表?

工作解决方案#1:即使文件只有一条推文,也将以JSON格式存储的推文消息转换为数组。此外,如果有多个推文,则需要在每条推文后插入一个逗号,但最后一条推文除外,以便将推文置于标准JSON格式。根据需要插入逗号后,以下代码可以正常工作:

 JArray o = JArray.Parse("[" + textFileOfOneOrMoreTweetsInStandardJson + "]");
 List<Tweet> tweets = JsonConvert.DeserializeObject <List<Tweet>> (o.ToString());

解决方案#2:根据需要放置逗号后,创建并使用覆盖读取的自定义转换器,并确定是否只有一条推文或多条推文,并根据该推文进行反序列化。使用此解决方案的示例: Deserializing JSON when sometimes array and sometimes object

我正在使用前者 - 使用解决方案#1而非解决方案#2的任何重大缺点?我不是在考虑替代解决方案吗?

未解决的问题:如何在反序列化之前针对模式验证各个JSON对象的存档?如果我像上面那样将对象视为数组,则在验证第一个对象并忽略其余对象后,json.net验证工具将停止。我想我可以以某种方式逐个浏览它们并在反序列化之前一次验证它们中的每一个,但这似乎是无效的并且会耗费时间,因为有成千上万的推文。

总而言之,JSON并不是真正设计用于在一个文本文件中将一个和几千个单独的JSON对象一起存档,因此使用该文件一直是一场艰苦的战斗。

旁注:我不关心序列化,我只需要通过将它们放入推文对象列表来分析LINQ的推文。在反序列化之前根据模式验证每条推文会很不错,但这可能太困难或耗费时间。

因为我无法在网络上的任何地方找到它并且它可以帮助其他人,所以我提供的是基于Twitter的API为Twitter推文创建的模式。但请注意,即使API反映字段不是可选字段,它们也在我的存档中,因此我需要指示可选的用于验证目的(令人惊讶的是,一条推文有可能包含许多JSON属性!)。

Twitter Tweet JSON架构

    {
  "$schema": "http://json-schema.org/schema#",
  "description": "Twitter API JSON Schema",
  "type": "object",
  "properties": {
    "annotations":{
      "optional":true,
      "type":[
        "object",
        "null"
      ],
      "properties":{
      }
    },
    "contributors":{
      "optional":true,
      "type":[
        "array",
        "null"
      ],
      "type":[
        "object",
        "null"
      ],
      "properties":{
        "id":{
          "optional":true,
          "type":"integer"
        },
        "id_str":{
          "optional":true,
          "type":"string"
        },
        "screen_name":{
          "optional":true,
          "type":"string"
        }
      }
    },
    "coordinates":{
      "optional":true,
      "type":[
        "object",
        "null"
      ],
      "properties":{
        "coordinates":{
          "optional":true,
          "type":[
            "array",
            "number"
          ]
        },
        "type":{
          "optional":true,
          "type":"string"
        }
      }
    },
    "created_at":{
      "optional":true,
      "type":"string"
    },
    "entities":{
      "optional":true,
      "type":"object",
      "properties":{
        "hashtags":{
          "optional":true,
          "type":"object",
          "type":"array",
          "properties":{
            "indices":{
              "type":"array",
              "type":"integer",
              "type":"integer"
            }
          }
        },
        "media":{
          "optional":true,
          "type":"object",
          "type":"array",
          "properties":{
            "display_url":{
            "optional":true,
              "type":"string"
              },
            "expanded_url":{
              "optional":true,
              "type":"string"
              },
            "id":{
              "optional":true,
              "type":"integer"
              },
            "id_str":{
              "optional":true,
              "type":"string"
              },
           "indices":{
              "optional":true,
              "type":"array",
              "type":"integer"
            },
            "media_url":{
              "optional":true,
              "type":"string"
              },
            "media_url_https":{
              "optional":true,
              "type":"string"
              },
            "sizes":{
              "optional":true,
              "type":"object",
              "properties":{
                "thumb":{
                  "optional":true,
                  "type":"object",
                  "properties":{
                    "h":{
                      "optional":true,
                      "type":"integer"
                      },
                    "resize":{
                      "optional":true,
                      "type":"string"
                      },
                    "w":{
                      "optional":true,
                      "type":"integer"
                    }
                  }
                },
                "large":{
                  "optional":true,
                  "type":"object",
                  "properties":{
                    "h":{
                      "optional":true,
                      "type":"integer"
                      },
                    "resize":{
                      "optional":true,
                      "type":"string"
                      },
                    "w":{
                      "optional":true,
                      "type":"integer"
                    }
                  }
                },
                "medium":{
                  "optional":true,
                  "type":"object",
                  "properties":{
                    "h":{
                      "optional":true,
                      "type":"integer"
                      },
                    "resize":{
                      "optional":true,
                      "type":"string"
                      },
                    "w":{
                      "optional":true,
                      "type":"integer"
                    }
                  }
                },
                "small":{
                  "optional":true,
                  "type":"object",
                  "properties":{
                    "h":{
                      "optional":true,
                      "type":"integer"
                      },
                    "resize":{
                      "optional":true,
                      "type":"string"
                      },
                    "w":{
                      "optional":true,
                      "type":"integer"
                    }
                  }
                }
              }
            }
          }
        },
        "urls":{
          "optional":true,
          "type":"object",
          "type":"array",
          "properties":{
            "display_url":{
              "optional":true,
              "type":"string"
            },
            "expanded_url":{
              "optional":true,
              "type":"string"
            },
            "indices":{
              "optional":true,
              "type":"array"
            },
            "url":{
              "optional":true,
              "type":"string"
            }
          }
        },
        "user_mentions":{
          "optional":true,
          "type":"object",
          "type":"array",
          "properties":{
            "id":{
              "optional":true,
              "type":"integer"
            },
            "id_str":{
              "optional":true,
              "type":"string"
            },
            "indices":{
              "optional":true,
              "type":"array"
            },
            "name":{
              "optional":true,
              "type":"string"
            },
            "screen_name":{
              "optional":true,
              "type":"string"
            }
          }
        }
      }
    },
    "favorited":{
      "optional":true,
      "type":"boolean"
    },
    "geo":{
      "optional":true,
      "type":[
        "object",
        "null"
      ],
      "properties":{
      }
    },
    "id":{
      "optional":true,
      "type":"integer"
    },
    "id_str":{
      "optional":true,
      "type":"string"
    },
    "in_reply_to_screen_name":{
      "optional":true,
      "type":[
        "string",
        "null"
      ]
    },
    "in_reply_to_status_id":{
      "optional":true,
      "type":[
        "integer",
        "null"
      ]
    },
    "in_reply_to_status_id_str":{
      "optional":true,
      "type":[
        "string",
        "null"
      ]
    },
    "in_reply_to_user_id":{
      "optional":true,
      "type":[
        "integer",
        "null"
      ]
    },
    "in_reply_to_user_id_str":{
      "optional":true,
      "type":[
        "string",
        "null"
      ]
    },
    "place":{
      "optional":true,
      "type":[
        "object",
        "null"
      ],
      "properties":{
        "country":{
          "optional":true,
          "type":"string"
        },
        "country_code":{
          "optional":true,
          "type":"string"
        },
        "full_name":{
          "optional":true,
          "type":"string"
        },
        "id":{
          "optional":true,
          "type":"string"
        },
        "name":{
          "optional":true,
          "type":"string"
        },
        "place_type":{
          "optional":true,
          "type":"string"
        },
        "url":{
          "optional":true,
          "type":"string"
        },
        "bounding_box":{
          "optional":true,
          "type":"object",
          "properties":{
            "coordinates":{
              "optional":true,
              "type":"array",
              "type":"array",
              "type":"array",
              "type":"array",
              "type":"array"
            },
            "type":{
              "optional":true,
              "type":"string"
            }
          }
        }
      }
    },
    "retweet_count":{
      "optional":true,
      "type":[
        "integer",
        "string"
      ]
    },
    "retweeted":{
      "optional":true,
      "type":"boolean"
    },
    "source":{
      "optional":true,
      "type":"string"
    },
    "text":{
      "optional":true,
      "type":"string"
    },
    "truncated":{
      "optional":true,
      "type":"boolean"
    },
    "user":{
      "optional":true,
      "type":"object",
      "properties":{
        "contributors_enabled":{
          "optional":true,
          "type":"boolean"
        },
        "created_at":{
          "optional":true,
          "type":"string"
        },
        "default_profile":{
          "optional":true,
          "type":"boolean"
        },
        "default_profile_image":{
          "optional":true,
          "type":"boolean"
        },
        "description":{
          "optional":true,
          "type":[
            "string",
            "null"
          ]
        },
        "favourites_count":{
          "optional":true,
          "type":"integer"
        },
        "follow_request_sent":{
          "optional":true,
          "type":[
            "boolean",
            "null"
          ]
        },
        "following":{
          "optional":true,
          "type":[
            "string",
            "null"
          ]
        },
        "followers_count":{
          "optional":true,
          "type":"integer"
        },
        "friend_count":{
          "optional":true,
          "type":"integer"
        },
        "geo_enabled":{
          "optional":true,
          "type":"boolean"
        },
        "id":{
          "optional":true,
          "type":"integer"
        },
        "id_str":{
          "optional":true,
          "type":"string"
        },
        "is_translator":{
          "optional":true,
          "type":"boolean"
        },
        "lang":{
          "optional":true,
          "type":"string"
        },
        "listed_count":{
          "optional":true,
          "type":"integer"
        },
        "location":{
          "optional":true,
          "type":[
            "string",
            "null"
          ]
        },
        "name":{
          "optional":true,
          "type":"string"
        },
        "notifications":{
          "optional":true,
          "type":"null"
        },
        "profile_background_color":{
          "optional":true,
          "type":"string"
        },
        "profile_background_image_url":{
          "optional":true,
          "type":"string"
        },
        "profile_background_image_url_https":{
          "optional":true,
          "type":"string"
        },
        "profile_background_tile":{
          "optional":true,
          "type":"boolean"
        },
        "profile_image_url":{
          "optional":true,
          "type":"string"
        },
        "profile_image_url_https":{
          "optional":true,
          "type":"string"
        },
        "profile_link_color":{
          "optional":true,
          "type":"string"
        },
        "profile_sidebar_border_color":{
          "optional":true,
          "type":"string"
        },
        "profile_sidebar_fill_color":{
          "optional":true,
          "type":"string"
        },
        "profile_text_color":{
          "optional":true,
          "type":"string"
        },
        "profile_use_background_image":{
          "optional":true,
          "type":"boolean"
        },
        "protected":{
          "optional":true,
          "type":"boolean"
        },
        "screen_name":{
          "optional":true,
          "type":"string"
        },
        "show_all_inline_media":{
          "optional":true,
          "type":"boolean"
        },
        "statuses_count":{
          "optional":true,
          "type":"integer"
        },
        "time_zone":{
          "optional":true,
          "type":[
            "string",
            "null"
          ]
        },
        "url":{
          "optional":true,
          "type":[
            "string",
            "null"
          ]
        },
        "utc_offset":{
          "optional":true,
          "type":[
            "integer",
            "null"
          ]
        },
        "verified":{
          "optional":true,
          "type":"boolean"
        }
      }
    }
  }
}

0 个答案:

没有答案