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.
Related
I am having some problems with create with JSON.Net. When I try to parse it, it gives me following error:
Additional text encountered after finished reading JSON content:
I tried validating it with http://json.parser.online.fr/ and it says "SyntaxError: Unexpected token ,".
My JSON is as below:
{"StaffID":"S01","StaffRank":"Manager"},{"StaffID":"S02","StaffRank":"Waiter"}
How to deserialize it?
You need to surround that with square brackets, which denotes that it's an array:
[{"StaffID":"S01","StaffRank":"Manager"},{"StaffID":"S02","StaffRank":"Waiter"}]
As of Release 11.0.1, Json.NET now natively supports parsing comma-delimited JSON in the same way it supports parsing newline delimited JSON:
New feature - Added support for reading multiple comma delimited values with JsonReader.SupportMultipleContent.
Thus the answer to Line delimited json serializing and de-serializing by Yuval Itzchakov should work here also. Define an extension method:
public static partial class JsonExtensions
{
public static IEnumerable<T> FromDelimitedJson<T>(TextReader reader, JsonSerializerSettings settings = null)
{
using (var jsonReader = new JsonTextReader(reader) { CloseInput = false, SupportMultipleContent = true })
{
var serializer = JsonSerializer.CreateDefault(settings);
while (jsonReader.Read())
{
if (jsonReader.TokenType == JsonToken.Comment)
continue;
yield return serializer.Deserialize<T>(jsonReader);
}
}
}
}
Then, given a data model created to hold an individual item in the comma-separated list such as:
public class RootObject
{
public string StaffID { get; set; }
public string StaffRank { get; set; }
}
You can deserialize the JSON string shown like so:
var jsonString = #"{""StaffID"":""S01"",""StaffRank"":""Manager""},{""StaffID"":""S02"",""StaffRank"":""Waiter""}";
var list = JsonExtensions.FromDelimitedJson<RootObject>(new StringReader(jsonString)).ToList();
This approach may be preferable when deserializing a very large sequence of comma-delimited objects from a large file, because it is not necessary to load the entire file into a string then add '[' and ']' to the beginning and end. In Performance Tips: Optimize Memory Usage Newtonsoft recommends deserializing large files directly from a stream, so instead a StreamReader can be passed into JsonExtensions.FromDelimitedJson() which will then stream through the file deserializing each object separately.
I'm developing a Rest Client using Spring Boot and Spring Framework (spring-boot-starter-parent 2.1.6.RELEASE)
I have a class representing a response object as shown below:
public class ValidateResponse {
private String ResponseCode;
private String ResponseDesc;
//getters and setters
//constructors using fields
//empty constructor
}
I'm creating a web-hook for an external api and I need to return a JSON object to for a specific endpoint (the JSON object properties must start with uppercase(s)). I'm calling returning the object from a PostMapping method nested in a RequestMapping root path:
#PostMapping("hooks/validate")
public ValidateResponse responseObj(#RequestHeader Map<String, String> headersObj) {
ValidateResponse response = new ValidateResponse("000000", "Success");
logger.info("Endpoint = hooks/validate | Request Headers = {}", headersObj);
return response;
}
However, when I hit the endpoint from postman I'm getting duplicate varialbes
{
"ResponseCode": "000000",
"ResponseDesc": "Success",
"responseCode": "000000",
"responseDesc": "Success"
}
I understand that the pojo-json conversion is handled by spring but I don't understand why the conversion is yielding duplicate variables.
Note: I know the ResponseDesc and the ResponseCode are not declared using the best standards for naming variables (camelCasing).
I've done some digging and according to the Java Language Specification
An identifier is an unlimited-length sequence of Java letters and Java digits, the first of which must be a Java letter.
and
The "Java letters" include uppercase and lowercase ASCII Latin letters A-Z (\u0041-\u005a), and a-z (\u0061-\u007a), and, for historical reasons, the ASCII underscore (_, or \u005f) and dollar sign ($, or \u0024). The $ character should be used only in mechanically generated source code or, rarely, to access pre-existing names on legacy systems.
So, I'm assuming its syntactically correct to define a variable using the Camelcase format [Need clarification on this].
I'm considering having to create the JSON object manually but I'd like to know the cause of this behaviour first. Any pointers are appreciated.
Jackson deserializes all the public fields that it comes across. However if you want Jackson to return the response in your expected element names (in your case elements starting with capital letters), make the fields private and annotate them with the #JsonProperty(expected_name_here). Your class file will typically looks as shown below
public class ValidateResponse {
#JsonProperty("ResponseDesc")
private String responseCode;
#JsonProperty("ResponseDesc")
private String responseDesc;
//getters and setters
//constructors using fields
//empty constructor
}
Note: The getters and setters for these fields should be public, otherwise Jackson won't see anything to deserialize in the class.
public class ValidateResponse {
#JsonProperty("ResponseDesc")
public String responseCode;
#JsonProperty("ResponseDesc")
public String responseDesc;
//getters and setters
//constructors using fields
//empty constructor
}
This must fix your problem, however I do not know the reason as it requires deep Jackson investigation.
EDIT
I found out the reason.
The field got duplicated because in you case you had:
2 public fields named in upper case -> they are to be processed by jackson
2 getters getResponseCode and getResponseDesc -> they are to be resolved
as accessors for properties responseCode and responseDesc accordingly.
Summing this up - you have 4 properties resolved by Jackson. Simply making your fields private will resolve your issue, however I still advise using JsonProperty approach.
I added a com.google.code.gson dependency in the projects pom.xml file to configure Spring Boot to use Gson (instead of the default jackson).
The Json object returned from the hooks/validate endpoint must have its property names starting with a capital letter. Using a java class to generate the response object was resulting to camelCased property names so I resolved to create the JSON response object manually. Here's the code for creating the custom JSON object:
public ResponseEntity<String> responseObj(#RequestHeader Map<String, String> headersObj) {
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentType(MediaType.APPLICATION_JSON);
JsonObject response = new JsonObject();
response.addProperty("ResponseCode", "00000000");
response.addProperty("ResponseDesc" , "Success");
logger.info("Endpoint = hooks/validate | Request Headers = {}", headersObj);
return ResponseEntity.ok().headers(responseHeaders).body(response.toString());
}
Note The JSON object is returned as a String so the response from the endpoint must have an additional header to define MediaType to inform the calling system that the response is in JSON format:
responseHeaders.setContentType(MediaType.APPLICATION_JSON);
then add the header to the response:
return ResponseEntity.ok().headers(responseHeaders).body(response.toString());
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
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
The Client side receives a formal JSON content "{\"Id\":[1,2,3],\"Size\":56}", but get an error in deserialization the byte array.
1 Error occurs in the statement below
IRestResponse<key> response = client.Execute<key>(request);
2 Error message is "No parameterless constructor defined for this object."
3 The object class in client size is the same as it's in server side:
public class key
{
public byte[] id { get; set; }
public int Size { set; get; }
}
4 I've tried passing object that contains string and integer by JSON format and that's all fine but byte array.
JsonDeserializer from RestSharp can not deserialize array. Instead of byte[] use List<byte>. For more information see https://github.com/restsharp/RestSharp/wiki/Deserialization
I have run into this issue, too. My solution was to use RestSharp to perform a raw execute and use Json.NET to deserialize the result:
var response = client.Execute(request);
var keyResponse = JsonConvert.DeserializeObject<key>(response.Content);
keyResponse should now be an instance of your key class deserialized from the JSON content.
In addition to Chris Hogan's reply, I'd like to point out that I got this error when RestSharp incorrectly used the default serializer instead of the custom JSON.NET serializer I had assigned.
The reason for this was that I added a handler with content type application/json whereas the API I was getting the response from returned the content as text/json.
So by changing the AddHandler call to AddHandler("text/json", jsonDeserializer), I resolved the issue.