javascript - array - Formato de data do ASP.NET MVC JsonResult



asp net mvc return json string (16)

Eu tenho uma ação de controlador que efetivamente simplesmente retorna um JsonResult do meu modelo. Então, no meu método eu tenho algo parecido com o seguinte:

return new JsonResult(myModel);

Isso funciona bem, exceto por um problema. Existe uma propriedade de data no modelo e isso parece ser retornado no resultado do Json da seguinte forma:

"\/Date(1239018869048)\/"

Como devo estar lidando com datas para que elas sejam retornadas no formato que eu preciso? Ou como eu manipulo esse formato acima no script?

https://ffff65535.com


Usando o jQuery para converter datas automaticamente com $.parseJSON

Nota : esta resposta fornece uma extensão jQuery que adiciona suporte automático ao formato de data ISO e .net.

Como você está usando o Asp.net MVC, suspeito que esteja usando o jQuery no lado do cliente. Eu sugiro que você leia este post que tem como usar $.parseJSON para converter datas automaticamente para você.

O Code suporta datas formatadas em Asp.net como as que você mencionou, bem como datas formatadas em ISO. Todas as datas serão automaticamente formatadas para você usando $.parseJSON() .


A comunicação do Ajax entre o cliente e o servidor geralmente envolve dados no formato JSON. Enquanto o JSON funciona bem para strings, números e booleanos, pode representar algumas dificuldades para datas devido à maneira como o ASP.NET as serializa. Como não tem nenhuma representação especial para datas, elas são serializadas como strings simples. Como uma solução, o mecanismo de serialização padrão do ASP.NET Web Forms e MVC serializa datas em um formato especial - / Date (ticks) / - onde ticks é o número de milissegundos desde 1º de janeiro de 1970.

Este problema pode ser resolvido de duas maneiras:

lado do cliente

Converta a string de data recebida em um número e crie um objeto de data usando o construtor da classe de data com os tiques como parâmetro.

function ToJavaScriptDate(value) {
  var pattern = /Date\(([^)]+)\)/;
  var results = pattern.exec(value);
  var dt = new Date(parseFloat(results[1]));
  return (dt.getMonth() + 1) + "/" + dt.getDate() + "/" + dt.getFullYear();

}

lado do servidor

A solução anterior usa um script do lado do cliente para converter a data em um objeto JavaScript Date. Você também pode usar o código do lado do servidor que serializa as instâncias .NET DateTime no formato de sua escolha. Para realizar essa tarefa, você precisa criar seu próprio ActionResult e depois serializar os dados da maneira que desejar.

referência: http://www.developer.com/net/dealing-with-json-dates-in-asp.net-mvc.html


Apenas para expandir a resposta do casperOne .

A especificação JSON não considera os valores de data. MS teve que fazer uma chamada, e o caminho que escolheram foi explorar um pequeno truque na representação javascript das strings: a string literal "/" é a mesma que "\ /", e uma string literal nunca será serializada para " \ / "(mesmo" \ / "deve ser mapeado para" \\ / ").

Consulte http://msdn.microsoft.com/en-us/library/bb299886.aspx#intro_to_json_topic2 para obter uma explicação melhor (role para baixo até "From JavaScript Literals to JSON")

Um dos pontos doloridos do JSON é a falta de um literal de data / hora. Muitas pessoas ficam surpresas e desapontadas ao saber disso quando encontram pela primeira vez o JSON. A explicação simples (consolar ou não) para a ausência de um literal de data / hora é que o JavaScript nunca teve um deles: O suporte para valores de data e hora em JavaScript é inteiramente fornecido através do objeto Date. A maioria dos aplicativos que usam JSON como formato de dados, portanto, geralmente tendem a usar uma sequência ou um número para expressar valores de data e hora. Se uma string for usada, geralmente você pode esperar que ela esteja no formato ISO 8601. Se um número é usado, em vez disso, em seguida, o valor é normalmente usado para significar o número de milissegundos no UTC (Universal Coordinated Time) desde epoch, em que epoch é definido como meia-noite de 1 de janeiro de 1970 (UTC). Novamente, isso é uma mera convenção e não faz parte do padrão JSON. Se você estiver trocando dados com outro aplicativo, precisará verificar sua documentação para ver como ele codifica valores de data e hora em um literal JSON. Por exemplo, o ASP.NET AJAX da Microsoft não usa nenhuma das convenções descritas. Em vez disso, ele codifica os valores .NET DateTime como uma string JSON, em que o conteúdo da string é / Date (ticks) / e onde os ticks representam milissegundos desde epoch (UTC). Então, 29 de novembro de 1989, 4:55:30, em UTC, está codificado como "\ / Date (628318530718) \ /".

Uma solução seria apenas analisar:

value = new Date(parseInt(value.replace("/Date(", "").replace(")/",""), 10));

No entanto, ouvi dizer que há uma configuração em algum lugar para obter o serializador para saída de objetos DateTime com a new Date(xxx) sintaxe de new Date(xxx) . Eu vou tentar descobrir isso.

O segundo parâmetro de JSON.parse() aceita uma função reviver onde prescreve como o valor originalmente produzido por, antes de ser retornado.

Aqui está um exemplo para a data:

var parsed = JSON.parse(data, function(key, value) {
  if (typeof value === 'string') {
    var d = /\/Date\((\d*)\)\//.exec(value);
    return (d) ? new Date(+d[1]) : value;
  }
  return value;
});

Veja os documentos de JSON.parse()


Aqui está a minha solução em Javascript - muito parecido com o JPot, mas mais curto (e possivelmente um pouco mais rápido):

value = new Date(parseInt(value.substr(6)));

"value.substr (6)" retira a parte "/ Date (", e a função parseInt ignora os caracteres não numéricos que ocorrem no final.

EDIT: intencionalmente deixei de fora o radix (o segundo argumento para parseInt); veja meu comentário abaixo . Além disso, observe que as datas ISO-8601 são preferidas em relação a esse formato antigo - portanto, esse formato geralmente não deve ser usado para novos desenvolvimentos. Veja a excelente biblioteca Json.NET para uma ótima alternativa que serializa datas usando o formato ISO-8601.

Para datas JSON formatadas com ISO-8601, apenas passe a string para o construtor Date:

var date = new Date(jsonDate); //no ugly parsing needed; full timezone support

Descobri que criar um novo JsonResult e retornando que é insatisfatório - ter que substituir todas as chamadas para return Json(obj) com o return new MyJsonResult { Data = obj } é uma dor.

Então eu imaginei, porque não apenas seqüestrar o JsonResult usando um ActionFilter :

public class JsonNetFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.Result is JsonResult == false)
        {
            return;
        }

        filterContext.Result = new JsonNetResult(
            (JsonResult)filterContext.Result);
    }

    private class JsonNetResult : JsonResult
    {
        public JsonNetResult(JsonResult jsonResult)
        {
            this.ContentEncoding = jsonResult.ContentEncoding;
            this.ContentType = jsonResult.ContentType;
            this.Data = jsonResult.Data;
            this.JsonRequestBehavior = jsonResult.JsonRequestBehavior;
            this.MaxJsonLength = jsonResult.MaxJsonLength;
            this.RecursionLimit = jsonResult.RecursionLimit;
        }

        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            var isMethodGet = string.Equals(
                context.HttpContext.Request.HttpMethod, 
                "GET", 
                StringComparison.OrdinalIgnoreCase);

            if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet
                && isMethodGet)
            {
                throw new InvalidOperationException(
                    "GET not allowed! Change JsonRequestBehavior to AllowGet.");
            }

            var response = context.HttpContext.Response;

            response.ContentType = string.IsNullOrEmpty(this.ContentType) 
                ? "application/json" 
                : this.ContentType;

            if (this.ContentEncoding != null)
            {
                response.ContentEncoding = this.ContentEncoding;
            }

            if (this.Data != null)
            {
                response.Write(JsonConvert.SerializeObject(this.Data));
            }
        }
    }
}

Isso pode ser aplicado a qualquer método que retorne um JsonResult para usar o JSON.Net:

[JsonNetFilter]
public ActionResult GetJson()
{
    return Json(new { hello = new Date(2015, 03, 09) }, JsonRequestBehavior.AllowGet)
}

que responderá com

{"hello":"2015-03-09T00:00:00+00:00"}

como desejado!

Você pode, se não se incomodar de chamar a comparação em cada solicitação, adicione isso ao seu FilterConfig :

// ...
filters.Add(new JsonNetFilterAttribute());

e todo o seu JSON será agora serializado com JSON.Net em vez do JavaScriptSerializer integrado.


Ele retorna o formato de data do servidor. Você precisa definir sua própria função.

function jsonDateFormat(jsonDate) {

// Changed data format;
return (new Date(parseInt(jsonDate.substr(6)))).format("mm-dd-yyyy / h:MM tt");

};


Eu tenho trabalhado em uma solução para este problema, pois nenhuma das respostas acima me ajudou de verdade. Eu estou trabalhando com o calendário semana jquery e precisava de minhas datas para ter informações de fuso horário no servidor e localmente na página. Depois de cavar um pouco, descobri uma solução que pode ajudar os outros.

Estou usando o asp.net 3.5, vs 2008, asp.net MVC 2 e calendário de semana jquery,

Primeiro, estou usando uma biblioteca escrita por Steven Levithan que ajuda a lidar com datas no lado do cliente, a biblioteca de datas de Steven Levithan . O formato isoUtcDateTime é perfeito para o que eu precisava. Na minha chamada jquery AJAX eu uso a função de formato fornecida com a biblioteca com o formato isoUtcDateTime e quando a chamada ajax atinge meu método de ação, o tipo de data e hora é definido como local e reflete o horário do servidor.

Quando envio datas para a minha página via AJAX, eu as envio como strings de texto formatando as datas usando "ddd, dd MMy aaaa HH ':' mm ':' ss 'GMT'zzzz". Esse formato é facilmente convertido pelo lado do cliente

var myDate = new Date(myReceivedDate);

Aqui está minha solução completa menos a fonte de Steve Levithan, que você pode baixar:

Controlador:

public class HomeController : Controller
{
    public const string DATE_FORMAT = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'zzzz";

    public ActionResult Index()
    {
        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        return View();
    }

    public ActionResult About()
    {
        return View();
    }


    public JsonResult GetData()
    {
        DateTime myDate = DateTime.Now.ToLocalTime();

        return new JsonResult { Data = new { myDate = myDate.ToString(DATE_FORMAT) } };
    }

    public JsonResult ReceiveData(DateTime myDate)
    {
        return new JsonResult { Data = new { myDate = myDate.ToString(DATE_FORMAT) } };
    }
}

Javascript:

<script type="text/javascript">

function getData() {
    $.ajax({
        url: "/Home/GetData",
        type: "POST",
        cache: "false",
        dataType: "json",
        success: function(data) {
            alert(data.myDate);
            var newDate = cleanDate(data.myDate);
            alert(newDate);
            sendData(newDate);
        }
    });
} 

function cleanDate(d) {
    if (typeof d == 'string') {
        return new Date(d) || Date.parse(d) || new Date(parseInt(d));
    }
    if (typeof d == 'number') {
        return new Date(d);
    }
    return d;
}

function sendData(newDate) {
    $.ajax({
        url: "/Home/ReceiveData",
        type: "POST",
        cache: "false",
        dataType: "json",
        data:
        {
            myDate: newDate.format("isoUtcDateTime")
        },
        success: function(data) {
            alert(data.myDate);
            var newDate = cleanDate(data.myDate);
            alert(newDate);
        }
    });
}

// bind myButton click event to call getData
$(document).ready(function() {
    $('input#myButton').bind('click', getData);
});
</script>

Espero que este exemplo rápido ajude os outros na mesma situação em que eu estava. Neste momento, parece funcionar muito bem com a serialização do Microsoft JSON e mantém minhas datas corretas em fusos horários.


Eu tive o mesmo problema e em vez de retornar o valor de data real eu usei ToString ("dd MMM yyyy") nele. Em seguida, no meu javascript eu usei nova data (datevalue), onde datevalue pode ser "01 jan 2009".


Há um pouco de respostas para lidar com o lado do cliente, mas você pode alterar o lado do servidor de saída, se desejar.

Existem algumas maneiras de abordar isso, vou começar com o básico. Você terá que subclassificar a classe JsonResult e substituir o método ExecuteResult. A partir daí, você pode adotar algumas abordagens diferentes para alterar a serialização.

Abordagem 1: A implementação padrão usa o JsonScriptSerializer . Se você der uma olhada na documentação, você pode usar o método RegisterConverters para adicionar JavaScriptConverters personalizados. Há alguns problemas com isso: O JavaScriptConverter é serializado para um dicionário, ou seja, ele leva um objeto e serializa para um dicionário Json. Para tornar o objeto serializado em uma string, é necessário um pouco de hack, veja post . Este hack em particular também escapará da string.

public class CustomJsonResult : JsonResult
{
    private const string _dateFormat = "yyyy-MM-dd HH:mm:ss";

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }

        HttpResponseBase response = context.HttpContext.Response;

        if (!String.IsNullOrEmpty(ContentType))
        {
            response.ContentType = ContentType;
        }
        else
        {
            response.ContentType = "application/json";
        }
        if (ContentEncoding != null)
        {
            response.ContentEncoding = ContentEncoding;
        }
        if (Data != null)
        {
            JavaScriptSerializer serializer = new JavaScriptSerializer();

            // Use your custom JavaScriptConverter subclass here.
            serializer.RegisterConverters(new JavascriptConverter[] { new CustomConverter });

            response.Write(serializer.Serialize(Data));
        }
    }
}

Abordagem 2 (recomendado): A segunda abordagem é começar com o JsonResult substituído e ir com outro serializador Json, no meu caso o serializador Json.NET . Isso não requer o hackery da abordagem 1. Aqui está minha implementação da subclasse JsonResult:

public class CustomJsonResult : JsonResult
{
    private const string _dateFormat = "yyyy-MM-dd HH:mm:ss";

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }

        HttpResponseBase response = context.HttpContext.Response;

        if (!String.IsNullOrEmpty(ContentType))
        {
            response.ContentType = ContentType;
        }
        else
        {
            response.ContentType = "application/json";
        }
        if (ContentEncoding != null)
        {
            response.ContentEncoding = ContentEncoding;
        }
        if (Data != null)
        {
            // Using Json.NET serializer
            var isoConvert = new IsoDateTimeConverter();
            isoConvert.DateTimeFormat = _dateFormat;
            response.Write(JsonConvert.SerializeObject(Data, isoConvert));
        }
    }
}

Exemplo de uso:

[HttpGet]
public ActionResult Index() {
    return new CustomJsonResult { Data = new { users=db.Users.ToList(); } };
}

Créditos adicionais: James Newton-King


Irritante, não é?

Minha solução foi alterar meu serviço WCF para que ele retornasse o DateTimes em um formato mais legível (não-Microsoft). Observe abaixo, o " UpdateDateOriginal ", que é o formato padrão de datas do WCF, e meu " UpdateDate ", que é formatado para algo mais legível.

Veja como fazer isso:

Alterando o formato de data do WCF

Espero que isto ajude.


Não é a maneira mais elegante, mas isso funcionou para mim:

var ms = date.substring(6, date.length - 2);
var newDate = formatDate(ms);


function formatDate(ms) {

    var date = new Date(parseInt(ms));
    var hour = date.getHours();
    var mins = date.getMinutes() + '';
    var time = "AM";

    // find time 
    if (hour >= 12) {
        time = "PM";
    }
    // fix hours format
    if (hour > 12) {
        hour -= 12;
    }
    else if (hour == 0) {
        hour = 12;
    }
    // fix minutes format
    if (mins.length == 1) {
        mins = "0" + mins;
    }
    // return formatted date time string
    return date.getMonth() + 1 + "/" + date.getDate() + "/" + date.getFullYear() + " " + hour + ":" + mins + " " + time;
}

Não é por nada, mas há outro caminho. Primeiro, construa sua consulta LINQ. Em seguida, construa uma consulta do resultado Enumerado e aplique o tipo de formatação que você deseja.

var query = from t in db.Table select new { t.DateField };
var result = from c in query.AsEnumerable() select new { c.DateField.toString("dd MMM yyy") };

Eu tenho que dizer, o passo extra é chato, mas funciona bem.


O que funcionou para mim foi criar um viewmodel que contivesse a propriedade date como uma string. Atribuindo a propriedade DateTime do modelo de domínio e chamando o .ToString () na propriedade date ao atribuir o valor ao viewmodel.

Um resultado JSON de um método de ação do MVC retornará a data em um formato compatível com a exibição.

Visualizar Modelo

public class TransactionsViewModel
{
    public string DateInitiated { get; set; }
    public string DateCompleted { get; set; }
}

Modelo de Domínio

public class Transaction{
   public DateTime? DateInitiated {get; set;}
   public DateTime? DateCompleted {get; set;}
}

Método de ação do controlador

public JsonResult GetTransactions(){

var transactions = _transactionsRepository.All;
        var model = new List<TransactionsViewModel>();

        foreach (var transaction in transactions)
        {
            var item = new TransactionsViewModel
            {
                ...............
                DateInitiated = transaction.DateInitiated.ToString(),
                DateCompleted = transaction.DateCompleted.ToString(),
            };

            model.Add(item);
        }
        return Json(model, JsonRequestBehavior.AllowGet);
}


Você pode usar este método:

String.prototype.jsonToDate = function(){
    try{
        var date;
        eval(("date = new " + this).replace(/\//g,''));
        return date;
    } 
    catch(e){
        return new Date(0);
    }
};

adicione o plugin jquery na sua página.

function JsonDateFormate(dateFormate, jsonDateTime) {
    return $.datepicker.formatDate(dateFormate, eval('new ' + jsonDateTime.slice(1, -1)));
};




json