I want to save a JSON object as a Document in Couchbase. The id of this document is supposed to be retrieved from this JSON object and the value is supposed to be this JSON object itself. Since this JSON is too complex, I haven't mapped it directly to any POJO class, but I have created a Simple POJO, which has two fields as shown below
#Document
public class SimplePojo{
#Id
private String id;
#Field()
private String complexJsonString;//the JSON string is stored in this variable
}
I also have a SimplePojoRepository as shown below
#Component
public interface SimplePojoRepository extends CouchbaseRepository<SimplePojo, String>{
}
Now, I am setting the id and complexJsonString manually before calling the save method:-
SimplePojo myObj= new SimplePojo();
myObj.setId(myKey);
myObj.setComplexJsonString(jsonString);
simplePojoRepository.save(myObj);
This is working fine, but it is saving the Document in below format
myKey: {
complexJsonString : {//the original json Object here}
}
but I don't want this, I want to save it like this:-
myKey : {//the original json Object here}
So, to make it clear, I don't want to save my JSON object as a value of complexJsonString but rather, directly as a value of the myKey . Can someone please guide me on how to achieve this?
If you want to store the complexJsonString as a nested entity within your main object, you have to transform it in a Pojo:
myObj.setSomeEntity(new SomeEntity())
You can easily transform your JSON-encoded String to object using jackson's ObjectMapper:
ObjectMapper mapper = new ObjectMapper();
mapper.readValue( jsonString, SomeEntity.class);
However, if you don't have control on the structure of this json, you will need to use the standard Java SDK instead of the Spring Data One:
JsonObject obj = JsonObject.create().put(this.documentTypeName, this.documentValue)
.put("attrNam1", "attrValue1")
.put("attrNam2", "attrValue2")
JsonDocument doc = JsonDocument.create(session.getId(), maxExpirationTime, obj);
bucket.upsert(doc)
In the case above, you will need to parse your JSON-encoded string using some lib (ex: gson/jackson) and then convert it to a couchbase JsonDocument.
Lastly, you could also leave your code as it is and use the N1QL function DECODE_JSON() whenever you need to access some property of this json string.
ex:
SELECT
i.itemName as itemName,
SUM(i.quantity) AS totalQuantity
FROM sessionstore s
UNNEST DECODE_JSON(s.sessionCart).shoppingCart.items i
WHERE s.sessionCart IS NOT MISSING
GROUP BY i.itemName
ORDER BY SUM(i.quantity) DESC
LIMIT 10
Related
I am trying to serialize a string that is returned from a http response and I am using netstandard1.0. Not a lot of serializing functions work in this framework, but I finally found a working function. Here is my code so far:
HttpResponseMessage Response = // initialized else where
var jsonTask = Response.Content.ReadAsStringAsync();
if (!jsonTask.IsCompleted) jsonTask.RunSynchronously();
string json = jsonTask.Result;
Data = JsonConvert.DeserializeObject<MyModel>(json);
However this does not deserialize I get from the http response. It throws an error that the DeserializeObject function is looking for a different format. When I run Result.Content.ReadAsStringAsync(), I get the result in the following format.
"[{\"key\":\"Password\",\"errors\":[\"The Password field is required.\"]},{\"key\":\"UserName\",\"errors\":[\"The UserName field is required.\"]},{\"key\":\"OrganizationUserName\",\"errors\":[\"The OrganizationUserName field is required.\"]}]"
Does anyone know how to deserialize this format?
If you define your MyModel as follows:
public class MyModel
{
public string key { get; set; }
public List<string> errors { get; set; }
}
You can deserialize as follows:
var list = JsonConvert.DeserializeObject<List<MyModel>>(json);
Notes:
I generated the c# definition for MyModel by uploading your JSON to http://json2csharp.com/.
The reason for the exception you are seeing trying to deserialize directly to MyModel is that your outer JSON container is an array, not an object. As explained in the standard, JSON has two types of container:
An array which is an ordered collection of values. An array begins with [ (left bracket) and ends with ] (right bracket). Values are separated by , (comma).
An object which is an unordered set of name/value pairs. An object begins with { (left brace) and ends with } (right brace).
In the Json.NET Serialization Guide: IEnumerable, Lists, and Arrays it is explained that JSON arrays are converted from and to .Net types implementing IEnumerable. So that's what you need to do.
If you know the array will contain no more than one element, you can use SingleOrDefault() to extract that single element:
Data = list.SingleOrDefault();
However, in the example included in you question, the outer array has 3 items, so this is not appropriate.
Sample fiddle.
I have a grails object that I am converting using def json = object as JSON. After I have it converted I want to add one more property called pin to the JSON which looks like the following.
[location:[lat:23.03, lon:72.58]]
Only way to do this so far seems like following
Serialize the DomainClass to JSON using grails.converters.json
Convert the JSON to string
Create JSONBoject using the string from Step 2
Add the property
Convert it back to String
Any other way to do this using grails.converters.json? I have tried using Gson but I do not want to go that route because I am getting many Circular Reference Errors
Try this:
domainInstance.properties + [pin: pinInstance] as JSON
I recently needed to do a similar thing. Some caveats:
This is using Grails 2.4.5
I use MongoDB as a backend. As such, I created an object marshaller for MongoDB domain classes. It is printed below, and you can wrap a similar marshaller for your domain class(es):
Marshaller:
class MongodbObjectMarshaller implements ObjectMarshaller<JSON> {
#Override
boolean supports(Object o) { return o?.properties?.dbo }
#Override
void marshalObject(Object obj, JSON converter) throws
ConverterException {
Map propertiesToOutput = obj.properties.dbo
propertiesToOutput.remove("_id") //don't print org.bson.types.ObjectId
propertiesToOutput.remove("version") //don't print gorm verson column
converter.build {
_id obj.id.toString()
propertiesToOutput.each{ entry ->
"$entry.key" entry.value
}
}
}
}
What that marshaller does, it allow in JSON output any of the domain class's properties. obj.properties.dbo is special to MongoDB, but for a regular domain class, you can just grab the properties and exclude the ones you don't need.
Then in my controller, this works:
domainInstance.pin = [location:[lat:23.03, lon:72.58]]
def content = tacticalCard as JSON
because my marshaller now picks up the pin property and prints it.
Is it possible to configure jackson to always add the type of the serialized object to the generated json output.
For example:
package org.acme;
class ClassA
{
String a;
String b;
}
and I want the generated json to be:
["org.acme.ClassA",{"a":"str1","b":"str2"}]
You can do that with enableDefaultTyping() of the ObjectMapper
e.g.
mapper.enableDefaultTyping(DefaultTyping.OBJECT_AND_NON_CONCRETE);
See ObjectMapper API
If your are free to change from Jackson and do not especially need the format to match the one your are showing you can try Genson http://code.google.com/p/genson.
For example if your requirement is to be able to deserialize interfaces or abstract classes based on the original type of the object you serialized you can do:
interface Entity {}
static class Person implements Entity {}
Genson genson = new Genson.Builder().setWithClassMetadata(true).create();
// json will be equal to {"#class":"my.package.Person"}
String json = genson.serialize(new Person());
// and now Genson is able to deserialize it back to Person using the information
// in the Json Object
Person person = (Person) genson.deserialize(json, Entity.class);
Another nice feature is the ability to define aliases for your classes, so you show less information in the json stream but also this allows you to do refactoring without worring of existing json streams (for example if you store it in a database).
Genson genson = new Genson.Builder().addAlias("person", Person.class).create();
// json value is {"#class": "person"}
String json = genson.serialize(new Person());
Have a look at the wiki.
We have used JSO for our JSON parsing in GWT client side. Now, we need to convert our Java objects to JSON string. I just wanted to understand, how we can achieve this? JSO overlay types was used for JSON parsing. Can it also be used to create a JSON request string or do we have to go by some other means?
Generating a JSON object in JavaScript is pretty simple. You can do it like this:
var obj = { "var1": "hello", "var2": "world" };
this will generate a JSON object with two varibles ("var1" and "var2") with their values ("hello", "world").
The Object can be converted into a String (for sending purposes) with the JSON.stringify(jso); method.
Generating JSON data from the java code isn't possible (well not with a usefull result) since all varibles are optimzed to single Strings, so applying this method wouldn't hava a usefull result (if even possible).
If you have already a JSO object (generated with something like safeeval). You can edit your varibles there, like this:
public final native void newValue(String newValue) /*-{
this.ValueName = newValue;
}-*/;
If you then want the object as string you have to define the following method in your JSO class:
public final native String returnAsString () /*-{
return JSON.stringify(this);
}-*/;
or use this in you Java class: String s = (new JSONObject(jso)).toString();.
This way you can edit your original intput data and send the original object back to the server.
BR
So I have a class that I was planning on using for simple JSON serialization.
public class Thing {
private int field1;
private String some_other_field;
private List<SubType> subs;
private list<AnotherType> another;
public String toJson() {
Gson g = new Gson();
g.toJson(this);
}
}
So the documentation shows that if you want to serialize generic types, you need to specify a TypeToken:
Type listtype = new TypeToken<List<SubType>>() {}.getType();
gson.toJson(subs, listtype);
But then, how does this work if I have a whole class I want to serialize for? Where do I get to specify the serialization type for those two List<> types so that I can just pass the whole object in and get a serialized output? Is that even possible?
From the doc it seems that if you serialize a complete object with toJson(...), it deals with the generics attributes properly.
toJson(Object)
"Note that this method works fine if the any of the object fields are of generic type, just the object itself should not be of a generic type"
What output did you get with your object ?