Converting a json string to a native .net object - mongodb

I need to convert a json to a native .net object using mongodb. The application is written in javascript/mvc.
One of the field is a datetime object and the toJson function in the mongodb driver formats this as: "Modified":{"$date":1319630804846}
I want to parse this json from the client using the same format, but can't find a function that does this.
In Newtonsoft.Json I used this code, but this fails because of the date field:
var jobject = JObject.parse(jsonAsString)
var myObject = jobject.ToObject<myObject>();
But with the mongoDb driver, all I can do is converting the string to a BsonDocument
var buffer = new JsonBuffer(json);
using (BsonReader reader = new JsonReader(buffer))
{
var doc = BsonDocument.ReadFrom(reader);
....
}

The BSON serialization format for DateTime is an Int64 containing the number of milliseconds since Unix Epoch. So if you were to create a DateTime of kind Utc set to jan 1 1970 and then create a TimeSpan with TotalMilliseconds set to the Int64, and add the two together you'd have the date in Utc. The same algorithm could be used in reverse as needed.

If you're using the official .NET driver, you can work with objects without going through the JSON serialization.
Check the following example of how easy this is:
class Child
{
public ObjectId id;
public string name;
public DateTime birthday;
}
class Program
{
static void Main(string[] args)
{
Child m = new Child();
m.name = "Micaiah";
m.birthday = DateTime.Parse("January 1, 2011");
Children.Insert<Child>(m);
foreach (Child kiddo in Children.FindAllAs<Child>())
{
Console.WriteLine("Kiddo: {0} {1}", kiddo.name, kiddo.birthday);
}
Console.ReadLine();
}
static MongoCollection Children
{
get
{
MongoServer s = MongoServer.Create("mongodb://localhost");
return s["demos"]["children"];
}
}
}
Here's the record as stored in MongoDB:
> db.children.findOne()
{
"_id" : ObjectId("4ea821b2dd316c1e70e34d08"),
"name" : "Micaiah",
"birthday" : ISODate("2011-01-01T06:00:00Z")
}
>

Use JSON.Net to de-serialize your Json into a JObject, and send that to MongoDB... if you have more concrete types in C#, you'll want to serialize/deserialize to/from that to JSON... then persist from your concrete object, or JObject.

Related

How to convert SinkRecord to JSON string?

Imagine myAPICreate requires a JSON string.
public void put(Collection<SinkRecord> collection) {
for (SinkRecord record : collection) {
JSONObject recordJson = toJSON(record.value());
String recordJsonString = recordJson.toString();
myAPICreate(recordJsonString);
}
}
toJSON is a helper I have defined which just takes the record and returns a JSONObject.
JSONObject json = new JSONObject()
.put("a", record.getString("a"))
.put("b", record.getString("b"))
.put("c", record.getString("c"));
I feel like I might be doing a lot of redundant work here. Is it necessary to have the code in put convert it to JSON or is there a way to use the converters so that record already comes in as JSON or a JSON string? Then I can just pass myAPICreate(record.value().toString()) without having to manually do it?
When you create a SinkRecord, you have a key & value schema w/ a key and value Object. Those objects should be Struct instances that must be created with the matching Schema
In the Connector configuration, you would then use JSONConverter (or other converter) to get the serialized output

Comparing LocalDate with date part of LocalDateTime in apache ignite

I have a certain records in ignite cache and I want to retrieve all records for current day. For this I need to compare LocalDateTime type field of cached object with Localdate object i.e LocalDate.now(). How do I write a query to do this. In oracle TODATE(date, format) does the same thing but this function is not present in H2.
cached field datetime: 2016-08-30T05:31
date instance : 2016-08-30
SQL will be like
String sql = "select * from cacheName where date='convert(datetime) to date'";
Is it possible in H2 ?
You can use custom SQL functions for this: https://ignite.apache.org/releases/mobile/org/apache/ignite/cache/query/annotations/QuerySqlFunction.html
For example, if your value class looks like this:
public class MyValue {
#QuerySqlField
private LocalDateTime time;
public MyValue(LocalDateTime time) {
this.time = time;
}
}
You can create a function like this:
public static class MyFunctions {
#QuerySqlFunction
public static String toDate(LocalDateTime time) {
return time.format(DateTimeFormatter.ISO_LOCAL_DATE);
}
}
And provide it in the configuration like this:
cacheCfg.setSqlFunctionClasses(MyFunctions.class);
The query will look like this:
select * from MyValue where toDate(time) = '2016-08-30'

Swagger Model Schema Response: alternate label for LocalDate in SpringFox

We are using Swagger 2.x and SpringFox 2.0 to document our REST service created with Spring MVC.
We have a REST response with a property List<LocalDate> dates.
In the Model Schema of the response, the label for dates is shown as 'LocalDate'. That is not intended: we would like to have 'date' or 'yyyy-MM-dd' instead.
We have this class:
public class SayHelloResponse {
private List<LocalDate> dates;
private String message;
public SayHelloResponse(String message, LocalDate... dates) {
this.message = message;
this.dates = ImmutableList.copyOf(dates);
}
public List<LocalDate> getDates() {
return dates;
}
public String getMessage() {
return message;
}
}
That results in this Model Schema:
{
"dates": [
"LocalDate"
],
"message": "string"
}
In the Model Schema, I would like to have LocalDate as 'date' or 'yyyy-MM-dd'. The way to do this seems to be with com.wordnik.swagger.annotations.ApiModelProperty but this does not have any effect (it is being picked up, as when I add #ApiModelProperty(hidden=true) it is hidden).
I created a sample rest project that shows the issue.
Any ideas how I can change LocalDate to 'date' or 'yyyy-MM-dd' in the Model Schema of Swagger?
There is a method in Docket object to replace models called directModelSubstitute(). You can use it like this to substitute LocalDate to Date object:
Docket#directModelSubstitute(LocalDate.class, Date.class)
The only problem with it that I found is that you can't change the date format.
See A/Q section in the official Springfox documentation, specifically question "How do we use Java 8 types esply. LocalDateTime?"
This is recommended in the official Springfox documentation, but doesn't effect:
Docket(DocumentationType.SWAGGER_2)..build().directModelSubstitute(LocalDate.class, java.sql.Date.class)
This effect but change format to date-time instead of date:
Docket(DocumentationType.SWAGGER_2)..build().directModelSubstitute(LocalDate.class, java.util.Date.class);
That's why I use the last one and ignore time part.

How to support embedded maps (with custom value types) in MongoDB GORM?

I would like to have an embedded document referred to by a map (as in 'class A' below). The environment is Grails + GORM + MongoDB.
is that possible, and if yes, how?
class A { // fails with IllegalArgumentException occurred when processing request: can't serialize class X in line 234 of org.bson.BasicBSONEncoder
static mapWith = "mongo"
Map<String, X> map = new HashMap<String, X>()
}
class B { // works
static mapWith = "mongo"
List<X> list = new ArrayList<X>()
}
class C { // works with primitive type values
static mapWith = "mongo"
Map<String, String> map = new HashMap<String, String>()
}
class X {
String data
public X(String data) {
this.data = data
}
}
The embedding works perfectly,as Art Hanzel advised.
However your problem comes from the fact that you try and use List genericity as a sort of constraint :
Map<String, X>
The problem is that Grails couldn't cope well with this syntax, first because Groovy doesn't support genericity.
However, the MongoDB plugin offers a very powerful functionality that lets you define custom type as Domain Class Properties : see here.
In your case you could have
class A {
static mapWith = "mongo"
MyClass map = new MyClass()
}
Then in your src/java for example you could for example implement a
class MyClass extends HashMap<String,X> { }
Then, of course, you have to define a special AbstractMappingAwareCustomTypeMarshaller to specify how to read and write the property in the DB.
An additional step could also be to add a custom validator to class A to check the validity of data...
The MongoDB Grails plugin documentation describes how to make embedded documents:
class Foo {
Address address
List otherAddresses
static embedded = ['address', 'otherAddresses']
}
Off the top of my head, you should be able to access these via the object graph. I don't see any reason why you shouldn't.
myFoo.address.myAddressProperty...

Jersey Marshall Map<Date,List>

I start understanding how jersey works with JAXB. But today i faced a particular case where i want to marshall a Map of (Date,List) entries:
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class MyClass{
#XmlJavaTypeAdapter(MapAdapter.class)
private Map<Date,List<MyObject>> = new TreeMap<Date,List<MyObject>>(new DateCompareDesc());
}
The goal here is to marshall a Map whose entry is a Date with its corresponding list of MyObject. the map is sorted in desc order.
For this i implemented an Adapter for Map (MapAdapter, following #Blaise Doughan's tutorial, http://blog.bdoughan.com/2010/07/xmladapter-jaxbs-secret-weapon.html). The problem is on the Date key. I have an Error : Unable to marshall java.util.Date. So i tried this new Date Adapter :
public class DateAdapter extends XmlAdapter<String, Date> {
#Override
public Date unmarshal(String v) throws Exception {
//not implemented
}
#Override
public String marshal(Date v) throws Exception {
return v.toString();
}
}
Where can i add #XmlJavaTypeAdapter(DateAdapter.class) so that Jersey could marhsall Date as key to my TreeMap?
Thanks.
JAXB supports the marshalling/unmarshalling of java.util.Date to the standard XML schema types: date, time, dateTime. You can control the type used with the #XmlSchemaType annotation.
http://blog.bdoughan.com/2011/01/jaxb-and-datetime-properties.html
If your date information is not represented as one of the standard XML schema types, you can use an XmlAdapter similar to the one I used the following answer to a similar question:
jaxb unmarshal timestamp
If you need to use the XmlAdapter approach, the #XmlJavaTypeAdapter annotation would be placed on the Date field of the adapted object representing the entry in the Map. Below is what this might look like based on my blog: http://blog.bdoughan.com/2010/07/xmladapter-jaxbs-secret-weapon.html.
import javax.xml.bind.annotation.XmlValue;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
public class MyMapEntryType {
#XmlAttribute
#XmlJavaTypeAdapter(DateAdapter.class)
public Date key;
public List<MyObject> value;
}