We are running .NET Core 2.1 on Linux. We do a POST with body below, and it seems for all 3 cases the datetime is converted to UTC time, instead of keeping the local time with offset as submitted. What is surprising is that even JSON properties deserialized to string are still showing converted value.
We are trying to retain the local value for further processing.
JSON:
{
"ts": "2020-09-27T01:23:27.047-04:00",
"tsTest": "2020-09-27T01:23:27.047-04:00",
"tsTest2": "2020-09-27T01:23:27.047-04:00"
}
Model:
public class HealthAssessmentResponseDto
{
[JsonProperty("ts")]
// public string LocalDttmStr { get; set; }
public DateTimeOffset LocalDttm { get; set; }
[JsonProperty("tsTest")]
public string LocalDttmStr { get; set; }
[JsonProperty("tsTest2")]
[JsonConverter(typeof(DateFormatConverter), "yyyy-MM-ddTHH:mm:ssK")]
public DateTimeOffset LocalDttmConverted { get; set; }
}
public class DateFormatConverter : Newtonsoft.Json.Converters.IsoDateTimeConverter
{
public DateFormatConverter(string format)
{
DateTimeFormat = format;
}
}
Result
{
"tranId": "7be8989c-c310-4b7a-a5a2-1706398f94f8",
"payload": {
"rto": true,
"message": "LocalDttmStr: 2020-09-27T05:23:27, LocalDttmConverted: 09/27/2020 05:23:27 +00:00, DatetimeOffset: 09/27/2020 05:23:27 +00:00"
}
}
Related
Having json string containing date field
{
"totalSize": 2,
"records": [
{
"Id": "5006C000008ZhEDQA0",
"CreatedDate": "2021-12-01T15:14:20.000+0000",
"CaseNumber": "01378682",
"Status": "Open"
},
{
"Id": "5006C000008ZhE00A0",
"CreatedDate": "2021-12-05T08:00:00.000+0000",
"CaseNumber": "01378692",
"Status": "Open"
}
]
}
I'm trying to do normal Deserialization where CreatedDate datatype is DateTime.
JsonSerializer.Deserialize<SFHistoryResponse>(stringResponse);
I'm getting
The JSON value could not be converted to System.DateTime. Path:
$.records[0].CreatedDate
is there any way to format JSON's date part before Deserialization
The Newtonsoft JSON library can deserialize the string properly without throwing an exception:
using Newtonsoft.Json;
var response = JsonConvert.DeserializeObject<SFHistoryResponse>(stringResponse);
In your case your classes need to be:
public class Record
{
public string Id { get; set; }
public DateTime CreatedDate { get; set; }
public string CaseNumber { get; set; }
public string Status { get; set; }
}
public class SFHistoryResponse
{
public int totalSize { get; set; }
public List<Record> records { get; set; }
}
and when you try to deserialize the json
SFHistoryResponse l = JsonConvert.DeserializeObject<SFHistoryResponse>(jsonString);
tested my self
tbResult.Text = "l.records[0].CreatedDate.ToString() - " + l.records[0].CreatedDate.ToString();
I have following object getting return from one of the API.
{{
"status": "success",
"data": {
"candles": [
[
"2020-11-01T18:30:00+00:00",
1065,
1079.95,
1051.1,
1072.3,
7183119
],
[
"2020-11-02T18:30:00+00:00",
1072,
1079.4,
1057.5,
1062.55,
7204782
],]
}
}}
I want to convert candle data into List<Historical>
Here is what I have tried
foreach (ArrayList item in historicalData["data"]["candles"])
historicals.Add(new Historical(item));
But this gives me following error:
Cannot convert type 'Newtonsoft.Json.Linq.JArray' to 'System.Collections.ArrayList
I have tried using JsonConvert.DeserializeObject to diretly convert the string into the object using following code:
foreach (var item in historicalData["data"]["candles"]) {
var historical = JsonConvert.DeserializeObject<Historical>(item.ToString());
But got this error:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'QuantConnect.Brokerages.Zerodha.Messages.Historical' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path '', line 1, position 1.
Historical definition:
public struct Historical
{
public Historical(dynamic data)
{
TimeStamp = Convert.ToDateTime(data[0], CultureInfo.InvariantCulture);
Open = Convert.ToDecimal(data[1], CultureInfo.InvariantCulture);
High = Convert.ToDecimal(data[2], CultureInfo.InvariantCulture);
Low = Convert.ToDecimal(data[3], CultureInfo.InvariantCulture);
Close = Convert.ToDecimal(data[4], CultureInfo.InvariantCulture);
Volume = Convert.ToUInt32(data[5], CultureInfo.InvariantCulture);
OI = data.Count > 6 ? Convert.ToUInt32(data[6], CultureInfo.InvariantCulture) : 0;
}
public DateTime TimeStamp { get; }
public decimal Open { get; }
public decimal High { get; }
public decimal Low { get; }
public decimal Close { get; }
public UInt32 Volume { get; }
public UInt32 OI { get; }
}
Is there a correct/elegant way to make it work. Also what I am missing something over here?
The main problem is this isn't valid json. However, let's fix it and assume it's correct. If this is what you are getting from some resources, I suggest you contact them and complain.
There are a bunch of ways to do this. Since you used JTokens, I will give you a similar answer.
Given
{
"status":"success",
"data":{
"candles":[
[
"2020-11-01T18:30:00+00:00",
1065,
1079.95,
1051.1,
1072.3,
7183119
],
[
"2020-11-02T18:30:00+00:00",
1072,
1079.4,
1057.5,
1062.55,
7204782
]
]
}
}
And
public class Historical
{
public DateTime TimeStamp { get; set; }
public decimal Open { get; set; }
public decimal High { get; set; }
public decimal Low { get; set; }
public decimal Close { get; set; }
public UInt32 Volume { get; set; }
public UInt32 OI { get; set; }
}
Usage
var jtoken = JToken.Parse(input);
var data = jtoken["data"]["candles"]
.Select(x => new Historical
{
TimeStamp = x[0].Value<DateTime>(),
Open = x[1].Value<decimal>(),
Low = x[2].Value<decimal>(),
High = x[3].Value<decimal>(),
Close = x[4].Value<decimal>()
//...
});
foreach (var item in data)
Console.WriteLine($"{item.TimeStamp},Open {item.Open},Low {item.Low} ...");
Output
2/11/2020 4:30:00 AM, Open 1065, Low 1079.95 ...
3/11/2020 4:30:00 AM, Open 1072, Low 1079.4 ...
Note : there are also many ways to deal with the datatime and how to configure Json.net or TryParse to give you the results you want. This is example is leaving this up to you and focusing solely on the projection.
If you need this done in the constructor
public struct Historical
{
public Historical(JToken x)
{
TimeStamp = x[0].Value<DateTime>();
Open = x[1].Value<decimal>();
Low = x[2].Value<decimal>();
High = x[3].Value<decimal>();
Close = x[4].Value<decimal>();
...
}
public DateTime TimeStamp { get; }
public decimal Open { get; }
public decimal High { get; }
public decimal Low { get; }
public decimal Close { get; }
...
}
...
var data = jtoken["data"]["candles"].Select(x => new Historical(x));
Not sure where I'm going wrong here. Serialized an object with newtonsoft to post to a web api. Running into error: "unexpected character encountered"
Here's my json:
{
"Eve": "wizz",
"familyid": "1006949",
"time": "07/21 05:45:59 AM",
"DogName": "Rocky",
"userid": "1006949"
}
Deserialize:
BtnData listObj = Newtonsoft.Json.JsonConvert.DeserializeObject<BtnData>(json.ToString());
Model:
public class BtnData
{
[JsonProperty("Eve")]
public string Eve { get; set; }
[JsonProperty("Familyid")]
public string Familyid { get; set; }
[JsonProperty("Time")]
public string Time { get; set; }
[JsonProperty("DogName")]
public string DogName { get; set; }
[JsonProperty("Userid")]
public string Userid { get; set; }
}
controller:
public ActionResult AddEvent([FromBody] BtnData json)
Solved by #knoop. Thank you !
json is already deserialized for you (it does that for you since you declared [FromBody] BtnData json. When you call ToString() on it it falls back to the default implementation which, for a class, just prints the name of it's type. And this name is invalid json so deserialization fails
I'm new to using Elasticsearch and I am using search on a services where part of the result I get back is formatted like this(names translated from other language):
accounting: {
properties: {
accountingInterval: {
properties: {
endDate: {
type: "date",
format: "dateOptionalTime"
},
startDate: {
type: "date",
format: "dateOptionalTime"
}
}
}
}
}
I can auto map it to object like this without a problem:
class MyBaseObject
{
public Accounting Accounting { get; set; }
//...some other values on base object
}
class Accounting
{
public AccountingInterval AccountingInterval { get; set; }
}
class AccountingInterval
{
[Date(Format = "dateOptionalTime")]
public DateTime? StartDate { get; set; }
[Date(Format = "dateOptionalTime")]
public DateTime? EndDate { get; set; }
}
Is there an way to get it to map to a simple object like this:
class MyBaseObject
{
[Date(Format = "dateOptionalTime")]
public DateTime? AccountingStartDate { get; set; }
[Date(Format = "dateOptionalTime")]
public DateTime? AccountingEndDate { get; set; }
//...some other values on base object
}
I tried setting the name attribute but it did not seem to work
class MyBaseObject
{
[Date(Name ="accounting.accountingInterval.startDate", Format = "dateOptionalTime")]
public DateTime? AccountingStartDate { get; set; }
[Date(Name ="accounting.accountingInterval.endDate", Format = "dateOptionalTime")]
public DateTime? AccountingEndDate { get; set; }
//...some other values on base object
}
As panchicore said in the comments, it would be possible to perform this flattening at index time with Ingest node and pipelines, and the type mapping in the index would reflect this structure.
If you're not responsible for indexing, then this is trickier to do. The mapping in NEST is used for both input to and output of documents from Elasticsearch. It'd be possible to control how JSON is deserialized to MyBaseObject by hooking up the Nest.JsonSerializer nuget package, and using Json.NET as the serializer for the client, and defining a custom JsonConverter for the MyBaseObject type. If you'd only like to do it for type aesthetics though, the effort is probably more than the value!
I am using Newtonsoft.Json in my project for json parsing from server.
public class MyObj
{
public DateTimeOffset TimeStamp { get; set; }
//other fields....
}
Then:
MyObj test = JsonConvert.DeserializeObject<MyObj>(jObject.ToString());
Test:
"TimeStamp": "2018-05-26T04:59:40:888Z" //Could not convert string to DateTimeOffset
"TimeStamp": "2018-05-26T04:59:40:88Z" //Could not convert string to DateTimeOffset
"TimeStamp": "2018-05-26T14:59:40:888Z" //Could not convert string to DateTimeOffset
"TimeStamp": "2018-05-26T14:59:40:88Z" //Could not convert string to DateTimeOffset
"TimeStamp": "2018-05-26T03:29:46.777Z" //works
"TimeStamp": "2018-05-26T13:29:46.77Z" //works
"TimeStamp": "2018-05-26T03:29:46.777Z" //works
"TimeStamp": "2018-05-26T13:29:46.77Z" //works
Error:
Newtonsoft.Json.JsonReaderException: Could not convert string to DateTimeOffset: 2018-05-27T04:59:40:887Z.
I am not sure why this happens, because the date is from server.
Edit:
{
"clientTimestamp": "2018-05-27T06:08:40:688Z",
"modifiedType": "",
"type": "TEXT",
"messageSize": 5,
"roomId": "689355a0-604b-11e8-ae6a-9d170520ec46",
"messageContent": "hello"
}
Update I finally found the issue. It was not the server response that I was parsing. It was my own object that I parsed. The description:
public class TempClass
{
public DateTime TimeStamp { get; set; }
}
Does not work
JObject jObject = new JObject();
jObject.Add("TimeStamp", DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss:fffZ"));
TempClass chatMessage = JsonConvert.DeserializeObject<TempClass>(jObject.ToString());
Works
JObject jObject = new JObject();
jObject.Add("TimeStamp", DateTime.Now);
TempClass chatMessage = JsonConvert.DeserializeObject<TempClass>(jObject.ToString());
Your timestamp is incorrect
Instead of 2018-05-27T06:08:40:688Z should be 2018-05-27T06:08:40.688Z
(the millisecond is separated by a dot . )
Try this
public class RootObject
{
public DateTime clientTimestamp { get; set; }
public string modifiedType { get; set; }
public string type { get; set; }
public long messageSize { get; set; }
public Guid roomId { get; set; }
public string messageContent { get; set; }
}
Then:
MyObj test = JsonConvert.DeserializeObject<RootObject>(jObject.ToString());
In fact
2018-05-27T06:08:40:688Z
Could not convert string to DateTime: 2018-05-27T06:08:40.688Z
2018-05-27T06:08:40.688Z
OK
It seems that this is happening because data from your server is not sent in the correct json format for the Date/Time, and you are trying to deserialize them.