Json.NET - 自定义转换器 - 字符串转整数

3
我遇到了关于Json.NET和omdbapi的问题。我试图从omdbapi检索信息,但其中一些属性让我头疼,特别是“imdbVotes”,因为它被写成像“321,364”这样的形式,所以我无法得到一个整数。
我敢打赌我需要一个自定义转换器,但我担心目前我真的不知道如何为我的特定问题创建一个。
所有其他属性都正常工作(目前我没有使用它们中的所有属性)。
以下是例如Snatch的响应:http://www.omdbapi.com/?i=&t=snatch 以下是我的类:
public class MovieJSON
{
    [JsonProperty(PropertyName = "Title")]
    public String Title { get; set; }

    [JsonProperty(PropertyName = "Year")]
    public int Year { get; set; }

    [JsonProperty(PropertyName = "Genre")]
    public String Genre { get; set; }

    [JsonProperty(PropertyName = "Director")]
    public String Director { get; set; }

    [JsonProperty(PropertyName = "Actors")]
    public String Actors { get; set; }

    [JsonProperty(PropertyName = "Plot")]
    public String Plot { get; set; }

    [JsonProperty(PropertyName = "Poster")]
    public String Poster { get; set; }

    [JsonProperty(PropertyName = "Metascore")]
    public int Metascore { get; set; }

    [JsonProperty(PropertyName = "imdbRating")]
    public decimal ImdbRating { get; set; }

    [JsonProperty(PropertyName = "imdbVotes")]
    public int ImdbVotes { get; set; }
}

更新 #1 :

如果属性的值为“N/A”,我该如何处理响应?有些电影(例如:http://www.omdbapi.com/?i=&t=four+rooms )的Metascore设置为 N/A。

更新 #2 :

另一个相关的问题。我正在使用EF6和MySQL,并且通过JSON解析来填充数据库中的电影数据。

这是我的Movie类:

[JsonObject(MemberSerialization.OptIn)]
[Table("movies")]
public class MovieJSON
{
    [Key]
    public int Id { get; set; }

    [JsonProperty(PropertyName = "Title")]
    [Column("title")]
    public String Title { get; set; }

    [JsonProperty(PropertyName = "Year")]
    [Column("year")]
    public int Year { get; set; }

    [JsonProperty(PropertyName = "Genre")]
    [Column("genre")]
    public String Genre { get; set; }

    [JsonProperty(PropertyName = "Director")]
    [Column("director")]
    public String Director { get; set; }

    [JsonProperty(PropertyName = "Actors")]
    [Column("actors")]
    public String Actors { get; set; }

    [JsonProperty(PropertyName = "Plot")]
    [Column("plot")]
    public String Plot { get; set; }

    [JsonProperty(PropertyName = "Poster")]
    [Column("poster")]
    public String Poster { get; set; }

    [JsonProperty(PropertyName = "Metascore")]
    public String Metascore { get; set; }

    [Column("metascore")]
    public int MetascoreInt
    {
        get
        {
            int result;
            if (int.TryParse(Metascore, NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out result))
                return result;
            return 0;
        }
    }

    [JsonProperty(PropertyName = "imdbRating")]
    public String ImdbRating { get; set; }

    [Column("imdb_rating")]
    public Decimal ImdbRatingDecimal
    {
        get
        {
            Decimal result;
            if (Decimal.TryParse(ImdbRating, out result))
                return result;
            return 0;
        }
    }

    [JsonProperty(PropertyName = "imdbVotes")]
    public String ImdbVotes { get; set; }

    [Column("imdb_votes")]
    public long ImdbVotesLong
    {
        get
        {
            long result;
            String stringToParse = ImdbVotes.Remove(ImdbVotes.IndexOf(','), 1);

            if (long.TryParse(stringToParse, out result))
                return result;
            return 0;
        }
    }

    [JsonProperty(PropertyName = "imdbID")]
    [Column("imdb_id")]
    public String ImdbID { get; set; }

    [JsonProperty(PropertyName = "type")]
    [Column("type")]
    public String Type { get; set; }

    public override string ToString()
    {
        String[] propertiesToIgnore = {"MetascoreInt", "ImdbRatingDecimal", "ImdbVotesLong"};
        var sb = new StringBuilder();

        PropertyInfo[] properties = GetType().GetProperties();

        foreach (PropertyInfo propertyInfo in properties)
        {
            if (propertiesToIgnore.Contains(propertyInfo.Name))
                continue;

            sb.AppendLine(String.Format("{0} : {1} ",
                propertyInfo.Name, propertyInfo.GetValue(this, null)));
        }

        return sb.ToString();
    }
}

这是我的EF6配置上下文类(我忽略了字符串字段,而是使用Helper字段,因为数据库配置为接受Metascore等整数):
protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<MovieJSON>().Ignore(e => e.Metascore).Ignore(e => e.ImdbRating).Ignore(e => e.ImdbVotes);
        base.OnModelCreating(modelBuilder);
    }

附加图像信息:

在插入数据库之前的对象值(所有值都已正确设置)

有效的XHTML http://imagizer.imageshack.us/v2/800x600q90/689/8x5m.png

数据库中的值:

有效的XHTML http://imagizer.imageshack.us/v2/800x600q90/844/nvc5.png

助手字段(MetascoreInt、ImdbRatingDecimal、ImdbVotesLong)返回零,我无法弄清原因。

任何帮助将不胜感激! :)

一切顺利


@D6mi,“N/A”只是一个字符串,你可以做同样的事情 ;) - Jim
@D6mi 抱歉可能我错过了,但是你是在使用WinForms还是带有绑定的WPF? - Jim
@Jim 好的,非常感谢! :) 顺便问一下,为了学习,我是否可以通过自定义转换器来实现更流畅的方法,而不需要额外的属性呢? - D6mi
@Jim,我有一个包含电影名称的.csv文件,并正在编写一个自定义工具来提取有关电影的额外信息(从omdbapi),然后我将使用Entity Framework将所有内容放入数据库中。该数据库将被ASP.NET MVC所使用。 - D6mi
@D6mi 给你一个快速提示...如果你得到了 Json,可以尝试使用 json2csharp,这样你就能快速了解你的响应对象的样式。 - Jim
显示剩余3条评论
1个回答

3
你可以有两个属性:一个是从IMDB获取的字符串属性,另一个是将字符串属性转换为整数的int属性。要进行转换,您可以使用巧妙的 NumberStyles.AllowThousands 标志。因此,您将拥有以下内容
[JsonProperty(PropertyName = "imdbVotes")]
public string ImdbVotes { get; set; }

public int ImdbVotesInt 
{ 
    get 
    {
        int result;
        if (int.TryParse(ImdbVotes, 
                NumberStyles.AllowThousands,
                CultureInfo.InvariantCulture, 
                out result))                    
            return result;  // parse is successful, use 'result'
        else
            return 0;       // parse is unsuccessful, return whatever default value works for you       
    }
}

谢谢您超快的回答:)。我明白您的意思,我尝试过这种解决方案,但我认为更好的方法是通过自定义转换器。我已经更新了我的问题,所以我想您会建议我对其他棘手的属性做同样的事情吗? - D6mi
@D6mi - 我不确定那种方式是否过于复杂了。当然,我也不知道你们项目的需求是什么。 - System Down

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接