.NET নিউটনসফট জেএসওন একটি পৃথক সম্পত্তির নামে মানচিত্রকে deserialize করে


294

আমি JSON স্ট্রিং অনুসরণ করেছি যা বাহ্যিক পক্ষ থেকে প্রাপ্ত received

{
   "team":[
      {
         "v1":"",
         "attributes":{
            "eighty_min_score":"",
            "home_or_away":"home",
            "score":"22",
            "team_id":"500"
         }
      },
      {
         "v1":"",
         "attributes":{
            "eighty_min_score":"",
            "home_or_away":"away",
            "score":"30",
            "team_id":"600"
         }
      }
   ]
}

আমার ম্যাপিং ক্লাস:

public class Attributes
{
    public string eighty_min_score { get; set; }
    public string home_or_away { get; set; }
    public string score { get; set; }
    public string team_id { get; set; }
}

public class Team
{
    public string v1 { get; set; }
    public Attributes attributes { get; set; }
}

public class RootObject
{
    public List<Team> team { get; set; }
}

প্রশ্ন আমি চাই না Attributes বর্গ নাম এবং attributes ফিল্ডের নাম মধ্যে Teamবর্গ। পরিবর্তে, আমি চাই যে এটির নামকরণ হোক TeamScoreএবং _ফিল্ডের নামগুলি থেকে সরিয়ে সঠিক নাম দেওয়া হোক।

JsonConvert.DeserializeObject<RootObject>(jsonText);

আমি নাম পরিবর্তন করতে পারেন Attributesকরতে TeamScore, কিন্তু যদি আমি ক্ষেত্র নাম পরিবর্তন ( attributesমধ্যে Teamবর্গ), এটি সঠিকভাবে deserialize করবে না এবং আমাকে দেয় null। আমি কীভাবে এটি কাটিয়ে উঠতে পারি?


উত্তর:


572

জসন.নেটের একটি রয়েছে JsonPropertyAttributeযা আপনাকে একটি জেএসএন সম্পত্তির নাম নির্দিষ্ট করার অনুমতি দেয়, তাই আপনার কোডটি হওয়া উচিত:

public class TeamScore
{
    [JsonProperty("eighty_min_score")]
    public string EightyMinScore { get; set; }
    [JsonProperty("home_or_away")]
    public string HomeOrAway { get; set; }
    [JsonProperty("score ")]
    public string Score { get; set; }
    [JsonProperty("team_id")]
    public string TeamId { get; set; }
}

public class Team
{
    public string v1 { get; set; }
    [JsonProperty("attributes")]
    public TeamScore TeamScores { get; set; }
}

public class RootObject
{
    public List<Team> Team { get; set; }
}

ডকুমেন্টেশন: সিরিয়ালাইজেশন বৈশিষ্ট্য


2
আমি কি একটি দায়েরের জন্য দুটি জসনপ্রপার্টি ব্যবহার করতে পারি?
আলী ইউসফি 11'15

1
পছন্দ করুন তবে ভাল প্রশ্নটি হবে, আপনি এটি থেকে কী প্রত্যাশা করবেন?
আউটকোল্ডম্যান

5
আমার একটি ইন্টারফেস রয়েছে, দুটি শ্রেণি এই ইন্টারফেসটি ব্যবহৃত হয়, তবে সার্ভারের ডেটাতে দুটি শ্রেণীর জন্য দুটি সম্পত্তি নাম রয়েছে, আমি আমার ইন্টারফেসে একটি সংস্থার জন্য দুটি জসনপ্রোপার্টি ব্যবহার করতে চাই।
আলী ইউসফি

আমরা কীভাবে এটি নিশ্চিত করতে পারি যে প্রতিক্রিয়া [বর্জিত বস্তু] ইটিএমিনস্কোরের জন্য মান এবং নয় আশি_মিনি_স্কোরের জন্য
গৌরবগণ

আমার ক্ষেত্রে আমি চূড়ান্ত প্রতিক্রিয়া RootObject পাঠাচ্ছি, কিন্তু যখন আমি চূড়ান্ত প্রতিক্রিয়া থেকে JSON যেমন পড়া, eighty_min_score এবং মান দেখানো হয় না EightyMinScore সঙ্গে
Gaurravs

115

আপনি যদি গতিশীল ম্যাপিং ব্যবহার করতে চান, এবং গুণাবলীর সাহায্যে আপনার মডেলটিকে বিশৃঙ্খলা করতে না চান, এই পদ্ধতির আমার পক্ষে কাজ হয়েছিল

ব্যবহার:

var settings = new JsonSerializerSettings();
settings.DateFormatString = "YYYY-MM-DD";
settings.ContractResolver = new CustomContractResolver();
this.DataContext = JsonConvert.DeserializeObject<CountResponse>(jsonString, settings);

লজিক:

public class CustomContractResolver : DefaultContractResolver
{
    private Dictionary<string, string> PropertyMappings { get; set; }

    public CustomContractResolver()
    {
        this.PropertyMappings = new Dictionary<string, string> 
        {
            {"Meta", "meta"},
            {"LastUpdated", "last_updated"},
            {"Disclaimer", "disclaimer"},
            {"License", "license"},
            {"CountResults", "results"},
            {"Term", "term"},
            {"Count", "count"},
        };
    }

    protected override string ResolvePropertyName(string propertyName)
    {
        string resolvedName = null;
        var resolved = this.PropertyMappings.TryGetValue(propertyName, out resolvedName);
        return (resolved) ? resolvedName : base.ResolvePropertyName(propertyName);
    }
}

1
এটি আমার উদ্দেশ্যটির জন্য কিছুটা সহজ করে তুলেছিল তবে এটি একটি আরও ভাল সমাধান তবে "" ক্লাটার আপ আপনি মডেল / ডোমেন ";)
আন্দ্রেয়াস

4
কি দারুন. এটি মহাকাব্য; এটি আরও অনেক বেশি স্থাপত্যগতভাবে সাধ্য পদ্ধতি।
ডেভিড বেটজ

1
এটি (যদি আপনি এর মধ্যে একটিরও বেশি তৈরি করেন) অভিধান সরিয়ে নেওয়ার পক্ষে মূল্যবান হতে পারে, সমস্ত সম্পত্তি ম্যাপিংয়ের জন্য বেস ক্লাস পর্যন্ত লুকিং কোড এবং তাদের বৈশিষ্ট্য যুক্ত করতে দেয় তবে ম্যাপিং কীভাবে ঘটে তার বিশদ উপেক্ষা করুন। জাস্টসন.নেট নিজেই এটিকে যোগ করার উপযুক্ত হতে পারে।
জেমস হোয়াইট

এটি গ্রহণযোগ্য উত্তর হওয়া উচিত কারণ @ ডেভিডবেটজ যেমন বলেছিলেন, এটি সেরা নকশা।
im1dermike

এই সমাধানটিও নেস্টেড বৈশিষ্ট্যগুলির সাথে কাজ করে? আমি নেস্টেড বৈশিষ্ট্যযুক্ত কোনও বস্তুর ডিসায়রিয়াল করার চেষ্টা করেছি এবং এটি কার্যকর হয় না।
আভি কে।

8

জ্যাকস দ্রবণে যুক্ত করা হচ্ছে। জসনপ্রপার্টি (বা তদ্বিপরীত) উপেক্ষা করার সময় আমাকে জসনপ্রোপার্টি এবং সিরিয়ালাইজ ব্যবহার করে ডিজিয়ালাইজেশন করা দরকার। রিফ্লেকশনহেল্পার এবং অ্যাট্রিবিউট হেল্পার হ'ল হেল্পার ক্লাস যা কোনও সম্পত্তির জন্য সম্পত্তি বা বৈশিষ্ট্যের তালিকা পান। কেউ যদি সত্যিই যত্ন করে তবে আমি অন্তর্ভুক্ত করতে পারি। নীচের উদাহরণটি ব্যবহার করে আপনি ভিউমডেলকে সিরিয়ালাইজ করতে পারেন এবং জাসনপ্রোপার্টি "রিকারিংপ্রাইস" হলেও "পরিমাণ" পেতে পারেন।

    /// <summary>
    /// Ignore the Json Property attribute. This is usefule when you want to serialize or deserialize differently and not 
    /// let the JsonProperty control everything.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class IgnoreJsonPropertyResolver<T> : DefaultContractResolver
    {
        private Dictionary<string, string> PropertyMappings { get; set; }

        public IgnoreJsonPropertyResolver()
        {
            this.PropertyMappings = new Dictionary<string, string>();
            var properties = ReflectionHelper<T>.GetGetProperties(false)();
            foreach (var propertyInfo in properties)
            {
                var jsonProperty = AttributeHelper.GetAttribute<JsonPropertyAttribute>(propertyInfo);
                if (jsonProperty != null)
                {
                    PropertyMappings.Add(jsonProperty.PropertyName, propertyInfo.Name);
                }
            }
        }

        protected override string ResolvePropertyName(string propertyName)
        {
            string resolvedName = null;
            var resolved = this.PropertyMappings.TryGetValue(propertyName, out resolvedName);
            return (resolved) ? resolvedName : base.ResolvePropertyName(propertyName);
        }
    }

ব্যবহার:

        var settings = new JsonSerializerSettings();
        settings.DateFormatString = "YYYY-MM-DD";
        settings.ContractResolver = new IgnoreJsonPropertyResolver<PlanViewModel>();
        var model = new PlanViewModel() {Amount = 100};
        var strModel = JsonConvert.SerializeObject(model,settings);

মডেল:

public class PlanViewModel
{

    /// <summary>
    ///     The customer is charged an amount over an interval for the subscription.
    /// </summary>
    [JsonProperty(PropertyName = "RecurringPrice")]
    public double Amount { get; set; }

    /// <summary>
    ///     Indicates the number of intervals between each billing. If interval=2, the customer would be billed every two
    ///     months or years depending on the value for interval_unit.
    /// </summary>
    public int Interval { get; set; } = 1;

    /// <summary>
    ///     Number of free trial days that can be granted when a customer is subscribed to this plan.
    /// </summary>
    public int TrialPeriod { get; set; } = 30;

    /// <summary>
    /// This indicates a one-time fee charged upfront while creating a subscription for this plan.
    /// </summary>
    [JsonProperty(PropertyName = "SetupFee")]
    public double SetupAmount { get; set; } = 0;


    /// <summary>
    /// String representing the type id, usually a lookup value, for the record.
    /// </summary>
    [JsonProperty(PropertyName = "TypeId")]
    public string Type { get; set; }

    /// <summary>
    /// Billing Frequency
    /// </summary>
    [JsonProperty(PropertyName = "BillingFrequency")]
    public string Period { get; set; }


    /// <summary>
    /// String representing the type id, usually a lookup value, for the record.
    /// </summary>
    [JsonProperty(PropertyName = "PlanUseType")]
    public string Purpose { get; set; }
}

2
আপনার IgnoreJsonPropertyResolver এর জন্য ধন্যবাদ, যেহেতু আমি একই জিনিসটি দেখছিলাম (কেবল সিরিয়ালাইজেশনে জসনপ্রপার্টি উপেক্ষা করুন)। দুর্ভাগ্যক্রমে আপনার সমাধানটি কেবল শীর্ষ স্তরের বৈশিষ্ট্যগুলির জন্য কাজ করে এবং নেস্টেড ধরণের নয়। সিরিয়ালাইজ করার সময় সমস্ত জসনপ্রপার্টি বৈশিষ্ট্যগুলি উপেক্ষা করার যথাযথ উপায় হ'ল CreatePropertyকন্ট্রাক্টরেসলভারে ওভাররাইড করা। সেখানে বেসটি কল করুন: var jsonProperty = base.CreateProperty(memberInfo, memberSerialization);এবং তারপরে সেট করুন jsonProperty.PropertyName = memberInfo.Name;। সবশেষে return jsonProperty;আপনার যা প্রয়োজন তা।
নাট কুক

1
এই সাহায্যকারীরা কি?
মৃতম্যানএন

1
@ নেটকুক আপনি আমাকে একটি নমুনা দেখাতে পারেন? আমার এখনই এটির খারাপভাবে প্রয়োজন
মৃতম্যান

4

রেন্টারিং ডটকমের উত্তরটি প্রসারিত করার মতো পরিস্থিতিতে যেখানে বিভিন্ন ধরণের পুরো গ্রাফটি যত্ন নেওয়া উচিত এবং আপনি দৃ strongly়ভাবে টাইপ করা সমাধান খুঁজছেন, এই শ্রেণিটি সাহায্য করতে পারে, নীচে ব্যবহার (সাবলীল) দেখুন। এটি ব্ল্যাক-লিস্ট বা টাইপ অনুসারে সাদা-তালিকা হিসাবে কাজ করে। এক ধরন উভয় (হতে পারে না সারকথা - বিশ্ব বাতিলের তালিকায় রয়েছে)।

public class PropertyFilterResolver : DefaultContractResolver
{
  const string _Err = "A type can be either in the include list or the ignore list.";
  Dictionary<Type, IEnumerable<string>> _IgnorePropertiesMap = new Dictionary<Type, IEnumerable<string>>();
  Dictionary<Type, IEnumerable<string>> _IncludePropertiesMap = new Dictionary<Type, IEnumerable<string>>();
  public PropertyFilterResolver SetIgnoredProperties<T>(params Expression<Func<T, object>>[] propertyAccessors)
  {
    if (propertyAccessors == null) return this;

    if (_IncludePropertiesMap.ContainsKey(typeof(T))) throw new ArgumentException(_Err);

    var properties = propertyAccessors.Select(GetPropertyName);
    _IgnorePropertiesMap[typeof(T)] = properties.ToArray();
    return this;
  }

  public PropertyFilterResolver SetIncludedProperties<T>(params Expression<Func<T, object>>[] propertyAccessors)
  {
    if (propertyAccessors == null)
      return this;

    if (_IgnorePropertiesMap.ContainsKey(typeof(T))) throw new ArgumentException(_Err);

    var properties = propertyAccessors.Select(GetPropertyName);
    _IncludePropertiesMap[typeof(T)] = properties.ToArray();
    return this;
  }

  protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
  {
    var properties = base.CreateProperties(type, memberSerialization);

    var isIgnoreList = _IgnorePropertiesMap.TryGetValue(type, out IEnumerable<string> map);
    if (!isIgnoreList && !_IncludePropertiesMap.TryGetValue(type, out map))
      return properties;

    Func<JsonProperty, bool> predicate = jp => map.Contains(jp.PropertyName) == !isIgnoreList;
    return properties.Where(predicate).ToArray();
  }

  string GetPropertyName<TSource, TProperty>(
  Expression<Func<TSource, TProperty>> propertyLambda)
  {
    if (!(propertyLambda.Body is MemberExpression member))
      throw new ArgumentException($"Expression '{propertyLambda}' refers to a method, not a property.");

    if (!(member.Member is PropertyInfo propInfo))
      throw new ArgumentException($"Expression '{propertyLambda}' refers to a field, not a property.");

    var type = typeof(TSource);
    if (!type.GetTypeInfo().IsAssignableFrom(propInfo.DeclaringType.GetTypeInfo()))
      throw new ArgumentException($"Expresion '{propertyLambda}' refers to a property that is not from type '{type}'.");

    return propInfo.Name;
  }
}

ব্যবহার:

var resolver = new PropertyFilterResolver()
  .SetIncludedProperties<User>(
    u => u.Id, 
    u => u.UnitId)
  .SetIgnoredProperties<Person>(
    r => r.Responders)
  .SetIncludedProperties<Blog>(
    b => b.Id)
  .Ignore(nameof(IChangeTracking.IsChanged)); //see gist

0

সিরিয়ালাইজ করার সময় আমি জসনপ্রোপার্টি বৈশিষ্ট্যগুলি ব্যবহার করছি তবে এটির ডিসিরিয়ালাইজ করার সময় সেগুলি উপেক্ষা করছি ContractResolver:

public class IgnoreJsonPropertyContractResolver: DefaultContractResolver
    {
        protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
        {
            var properties = base.CreateProperties(type, memberSerialization);
            foreach (var p in properties) { p.PropertyName = p.UnderlyingName; }
            return properties;
        }
    }

ContractResolverশুধু বর্গ সম্পত্তি নাম (কামিজ এর সমাধান থেকে সরলীকৃত) প্রতি সম্পত্তি ফিরে সেট করে। ব্যবহার:

var airplane= JsonConvert.DeserializeObject<Airplane>(json, 
    new JsonSerializerSettings { ContractResolver = new IgnoreJsonPropertyContractResolver() });
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.