Удалить пустые свойства объекта, отправленного Json MVC
namespace Booking.Areas.Golfy.Models
{
public class Time
{
public string time { get; set; }
public int holes { get; set; }
public int slots_available { get; set; }
public decimal? price { get; set; }
public int? Nextcourseid { get; set; }
public bool ShouldSerializeNextcourseid
{
get
{
return this.Nextcourseid != null;
}
}
public bool? allow_extra { get; set; }
public bool ShouldSerializeallow_extra
{
get
{
return this.allow_extra != null;
}
}
}
}
namespace Booking.Areas.Golfy.Controllers
{
public class TeetimesController : Controller
{
//
// GET: /Golfy/Teetimes/
public ActionResult Index(
string date,
int? courseid = null,
int? clubid = null,
int? holes = null,
int? available = null,
int? prices = null
)
{
var DateFrom = DateTime.ParseExact(date, "yyyy-MM-dd", CultureInfo.InvariantCulture);
Teetimes r = BookingManager.GetBookings(new Code.Classes.Params.ParamGetBooking()
{
ClubID = clubid
, DateFrom = DateFrom
, DateTo = DateFrom.AddDays(1)
, GroundID = courseid
});
return Json(r, JsonRequestBehavior.AllowGet);
}
}
}
Webservice выше возвращает строку json с несколькими значениями времени.
Я хотел бы, чтобы свойства Nextcourseid и allow_extra были исключены из вывода, когда их значения равны нулю.
Я попробовал ShouldSerializeXxx, но он не работает.
FYI: Я также пробовал [ScriptIgnore], который работает, но не является условным.
Ответы
Ответ 1
Вы не можете использовать значение по умолчанию Json ActionResult
для удаления нулевых свойств.
Вы можете посмотреть JSON.NET, у него есть атрибут, который вы можете установить для удаления свойства, если оно равно null
[JsonProperty(NullValueHandling=NullValueHandling.Ignore)]
Или, если вы не хотите использовать другие библиотеки, вы можете создать свой собственный пользовательский ActionResult json и зарегистрировать новый конвертер по умолчанию JavaScriptSerializer
, например:
public class JsonWithoutNullPropertiesResult : ActionResult
{
private object Data { get; set; }
public JsonWithoutNullPropertiesResult(object data)
{
Data = data;
}
public override void ExecuteResult(ControllerContext context)
{
HttpResponseBase response = context.HttpContext.Response;
response.ContentType = "application/x-javascript";
response.ContentEncoding = Encoding.UTF8;
if (Data != null)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { new NullPropertiesConverter() });
string ser = serializer.Serialize(Data);
response.Write(ser);
}
}
}
public class NullPropertiesConverter : JavaScriptConverter
{
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
var toSerialize = new Dictionary<string, object>();
foreach (var prop in obj.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Select(p => new
{
Name = p.Name,
Value = p.GetValue(obj)
})
.Where(p => p.Value != null))
{
toSerialize.Add(prop.Name, prop.Value);
}
return toSerialize;
}
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
throw new NotImplementedException();
}
public override IEnumerable<Type> SupportedTypes
{
get { return GetType().Assembly.GetTypes(); }
}
}
И теперь, на ваш взгляд:
public ActionResult Index()
{
Teetimes r = BookingManager.GetBookings();
return new JsonWithoutNullPropertiesResult(t);
}
Ответ 2
У меня всегда были проблемы с встроенным json-сериализатором, поэтому я использую Json.NET. Здесь небольшой пример тестирования этих двух сериализаторов:
public class Model {
public int Id { get; set; }
public string Name { get; set; }
public bool ShouldSerializeName() {
return Name != null;
}
}
class Program {
static void Main(string[] args) {
var t1 = new Model {
Name = "apw8u3rdmapw3urdm",
Id = 298384
};
var t2 = new Model {
Id = 234235
};
Test(t1);
Test(t2);
}
static void Test(Model model) {
Console.WriteLine("JSon from .Net: {0}", ToJson(model));
Console.WriteLine("JSon from JSon.Net: {0}", ToDotNetJson(model));
}
static string ToJson(Model model) {
var s = new JavaScriptSerializer();
return s.Serialize(model);
}
static string ToDotNetJson(Model model) {
return JsonConvert.SerializeObject(model);
}
}
Вы должны включить System.Web.Extensions
в качестве зависимости и установить Json.Net
с помощью nuget, чтобы этот пример работал.
Вот некоторая форма документации Json.NET и встроенный в сериализатор Framework
Ответ 3
Полученные ответы являются interresting, но я начал использовать DataContractJsonSerializer тем временем.
И он отлично справляется с работой без необходимости использования сторонней структуры (хотя JSON.Net действительно кажется широко используемым).
public ActionResult Index(
string date
, int? courseid = null
, int? clubid = null
, int? holes = null
, int? available = null
, int? prices = null
)
{
var DateFrom = DateTime.ParseExact(date, "yyyy-MM-dd", CultureInfo.InvariantCulture);
MTeetimes r = BookingManager.GetBookings(new Code.Classes.Params.ParamGetBooking()
{
ClubID = clubid
, DateFrom = DateFrom
, DateTo = DateFrom.AddDays(1)
, GroundID = courseid
});
// return Json(r, JsonRequestBehavior.AllowGet);
string response;
var serializer = new DataContractJsonSerializer(typeof(MTeetimes));
// Serialize
using (var ms = new MemoryStream())
{
serializer.WriteObject(ms, r);
response = Encoding.Default.GetString(ms.ToArray());
}
return Content(response);
}
[DataContract]
public class Time
{
[DataMember(Name="time", EmitDefaultValue = false)]
public string Time
{
get;
set;
}
[DataMember(Name = "holes", EmitDefaultValue = false)]
public int Holes
{
get;
set;
}
[DataMember(Name = "slots_available", EmitDefaultValue = false)]
public int Slots_available
{
get;
set;
}
[DataMember(Name = "price", EmitDefaultValue = false)]
public decimal? Price
{
get;
set;
}
[DataMember(Name = "nextcourseid", EmitDefaultValue = false)]
public int? Nextcourseid
{
get;
set;
}
[DataMember(Name = "allow_extra", EmitDefaultValue = false)]
public bool? Allow_extra
{
get;
set;
}
}