I am getting some response :
var xxx_api = { "user" : {
"name":"satishpandey",
"sites":[
{
"name":"SEO Product",
"url":"http://www.xxx.com/"
} ]
}};
I want to exclude all the string those are outside json data.
var xxx_api and ; are needs to be excluded.
Is there anything in jackson to exclude these strings?
Assuming you are using this in a get/post (restful-like) method, maybe that has to do with the header of the webservice method you are using. I am using REST and I am able to specify the format I want to receive the json input like this
#POST
#Path("/post")
#Consumes(MediaType.APPLICATION_JSON)
public Response myMethod(#FormParam("post") String jsonInput){
// ...
// use jsonInput
mapper.readValue(jsonInput, ...);
// ...
}
Considering this, I guess the input written to the var jsonInput (in the header) would be
{ "user" : {
"name":"satishpandey",
"sites":[
{
"name":"SEO Product",
"url":"http://www.xxx.com/"
} ]
}};
I didn't find any solutions for it in jackson. Now I am using String.substring() method for getting the desired results.
StringBuilder stringBuilder = new StringBuilder(jsonString);
stringBuilder.replace(0, stringBuilder.indexOf("{"), "");
stringBuilder.replace(stringBuilder.lastIndexOf("}") + 1, stringBuilder.length(), "");
It is working perfectly for me.
Related
I want to POST some custom JSON to my postgres jsonb column via postman using the below request.
The custom part is sent in the "Settings" > "data" node. I don't want to apply the custom part to a model I just want to send in any kind of json and store it.
{
"name": "Test",
"settings": {
"data": {
"customdata": "hello",
"custommore": "bye"
}
}
}
The "data" node is modelled - like this:
public string Data { get; set; } //I have tried JSONDocument and Jsonb types to no avail.
Postman errors with this:
"errors": {
"$.settings.data": [
"The JSON value could not be converted to System.String. Path: $.settings.data | LineNumber: 3 | BytePositionInLine: 17."
]
}
The request doesn't even hit my controller method. I think it is because the customdata and custommore is not mapped to a model.
Is there a way of sending in custom JSON data that is not fixed to a model of any kind - or must it be part of a model?
I'm struggling to find anything about this that doesn't relate to EF core which is not what I am using.
You can use custom model binding,and get json data from HttpContext.Request.Body,and then use sonConvert.DeserializeObject to get json object.You can set the data to the format you want.
Here is a demo:
DataBinder:
public class DataBinder:IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var model1 = new Customer();
using (var reader = new StreamReader(bindingContext.HttpContext.Request.Body))
{
var body = reader.ReadToEndAsync();
var mydata = JsonConvert.DeserializeObject<JObject>(body.Result);
model1.Name = mydata["name"].ToString();
model1.Settings = new Settings
{
Data = mydata["settings"]["data"].ToString()
};
}
bindingContext.Result = ModelBindingResult.Success(model1);
return Task.CompletedTask;
}
}
Controller:
public IActionResult TestCustomModelBinding([ModelBinder(BinderType = typeof(DataBinder))]Customer customer) {
return Ok();
}
result:
Sorry but I didn't explain it very well. I edit my question again:
I have an angular 4 application and I use json2typescript to convert from json to object and vice versa but I have a problem because I have a class structure and the response json from an external api has another structure. Example:
Customer {
#JsonProperty('idCardNumber', String)
idCardNumber: string = undefined;
#JsonProperty('rolInfo.name',String)
name: string = undefined;
#JsonProperty('rolInfo.surname',String)
surname: string = undefined;
}
External Json API Reponse:
{
"idCardNumber": "08989765F",
"rolInfo": {
"name": "John"
"surname: "Smith"
}
}
So, I would like to map from the json above to my Customer object and not to change my structure. I tried to put 'rolInfo.name' into the JsonProperty, but that doesn't work.
Change your Customer class to something like below
Customer {
#JsonProperty('idCardNumber', String)
idCardNumber: string = undefined;
#JsonProperty('rolInfo', Any)
rolInfo: any = {}; // if you set this to undefined, handle it in getter/setter
get name(): string {
return this.rolInfo['name'];
}
set name(value: string) {
this.rolInfo['name'] = value;
}
get surname(): string {
return this.rolInfo['surname'];
}
set surname(value: string) {
this.rolInfo['surname'] = value;
}
}
That should do it
Seems like the response JSON is already in a good format and you don’t need to do the conversion.
I would recommend creating models as they allow for serialization and deserialization when making API calls and binding the response to that model.
My json file is mostly an array that contain objects but the list is incomplete, so I can't use the last entry. I would like to deserialize the rest of the file while discarding the last invalid entry
[ { "key" : "value1" }, { "key " : "value2"}, { "key
Please tell me if there is a way using Newtonsoft.Json library, or do I need some preprocessing.
Thank you!
Looks like on Json.NET 8.0.3 you can stream your string from a JsonTextReader to a JTokenWriter and get a partial result by catching and swallowing the JsonReaderException that gets thrown when parsing the truncated JSON:
JToken root;
string exceptionPath = null;
using (var textReader = new StringReader(badJson))
using (var jsonReader = new JsonTextReader(textReader))
using (JTokenWriter jsonWriter = new JTokenWriter())
{
try
{
jsonWriter.WriteToken(jsonReader);
}
catch (JsonReaderException ex)
{
exceptionPath = ex.Path;
Debug.WriteLine(ex);
}
root = jsonWriter.Token;
}
Console.WriteLine(root);
if (exceptionPath != null)
{
Console.WriteLine("Error occurred with token: ");
var badToken = root.SelectToken(exceptionPath);
Console.WriteLine(badToken);
}
This results in:
[
{
"key": "value1"
},
{
"key ": "value2"
},
{}
]
You could then finish deserializing the partial object with JToken.ToObject. You could also delete the incomplete array entry by using badToken.Remove().
It would be better practice not to generate invalid JSON in the first place though. I'm also not entirely sure this is documented functionality of Json.NET, and thus it might not work with future versions of Json.NET. (E.g. conceivably Newtonsoft could change their algorithm such that JTokenWriter.Token is only set when writing is successful.)
You can use the JsonReader class and try to parse as far as you get. Something like the code below will parse as many properties as it gets and then throw an exception. This is of course if you want to deserialize into a concrete class.
public Partial FromJson(JsonReader reader)
{
while (reader.Read())
{
// Break on EndObject
if (reader.TokenType == JsonToken.EndObject)
break;
// Only look for properties
if (reader.TokenType != JsonToken.PropertyName)
continue;
switch ((string) reader.Value)
{
case "Id":
reader.Read();
Id = Convert.ToInt16(reader.Value);
break;
case "Name":
reader.Read();
Name = Convert.ToString(reader.Value);
break;
}
}
return this;
}
Code taken from the CGbR JSON Target.
the second answer above is really good and simple, helped me out!
static string FixPartialJson(string badJson)
{
JToken root;
string exceptionPath = null;
using (var textReader = new StringReader(badJson))
using (var jsonReader = new JsonTextReader(textReader))
using (JTokenWriter jsonWriter = new JTokenWriter())
{
try
{
jsonWriter.WriteToken(jsonReader);
}
catch (JsonReaderException ex)
{
exceptionPath = ex.Path;
}
root = jsonWriter.Token;
}
return root.ToString();
}
creating hard coded json is easy, e.g.
String createJson(Person person, list<Account> accounts) {
def builder = new JsonBuilder()
def json = builder {
person person
accounts accounts
}
return builder.toPrettyString()
}
The above works, and produces something like this:
{
"person":{
username": "user"
"firstName": "test"
}
"accounts":[
{
"balance": "200829.00",
"currency": "CRD",
"id": 1,
}
]
}
The problem is we have a REST api, which returns JSON. Curently, we have a lot of duplicate code, as we can't find a generic way to generate different parts of the JSON api response and combine them together and render the result, ether by merging json strings, or by dynamically buidling the json from a map, e.g the following doesnt work:
String createJson(Map map) {
def builder = new JsonBuilder()
def root = builder {
map.collect { key, value ->
"$key" value
}
}
return builder.toPrettyString()
}
then calling it like this:
Person person = someMethodToGetAPerson()
List<Account> accounts = someMethodToGetAccounts(person)
Map map = ["person", person, "accounts", accounts]
String json = createJson(map)
render(status: 200, contentType: 'application/json', text: json)
However, this fails, with a stack overflow in the bowels of grails.
In addition, we have defined several json marshallers which must be used, e.g.
JSON.registerObjectMarshaller(Account) {
return [balance: formatter.format(it.balance)....
}
Any ideas?
What I could understand is you want to convert a map into JSON string. For that you can use grails.converters.JSON class. For example
Person person = someMethodToGetAPerson()
List<Account> accounts = someMethodToGetAccounts(person)
Map map = [person: person, accounts: accounts]
String json = new JSON(map).toString()
The toString() method also takes an boolean value for preety printing. And it should honor your registered marshallers
I'm working on something that involved using the Bit.ly API, and allow the user to select theformat (Text, XML, Json) the text & XML are completed. This is the Json result that is returned when you shorten a URL:
{
"status_code": 200,
"status_txt": "OK",
"data":
{
"long_url": "http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}",
"url": "http:\/\/rlm.cc\/gtYUEd",
"hash": "gtYUEd",
"global_hash": "evz3Za",
"new_hash": 0
}
}
And this C# code works just fine to parse it and get the short URL:
var serializer2 = new JavaScriptSerializer();
var values2 = serializer2.Deserialize<IDictionary<string, object>>(json);
var results2 = values2["data"] as IDictionary<string, object>;
var shortUrl2 = results2["url"];
expandedUrl = results2["url"].ToString();
return results2["url"].ToString();
Now here's the Json sent back when expanding a URL:
{
"status_code": 200,
"status_txt": "OK",
"data":
{
"expand":
[
{
"short_url": "http:\/\/rlm.cc\/gtYUEd",
"long_url": "http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}",
"user_hash": "gtYUEd",
"global_hash": "evz3Za"
}
]
}
}
Ad that's where my problem begins, how can I change my current C# to be able to handle both scenarios, because as you can see their vastly different from each other. Any ideas?
I usually use Json.NET to cherrypick values out of JSON documents. The syntax is very concise. If you reference NewtonSoft.Json.dll and use Newtonsoft.Json.Linq, you can write the following:
var job = JObject.Parse(jsonString);
if (job["data"]["expand"] == null)
{
Console.WriteLine((string)job["data"]["url"]);
}
else
{
Console.WriteLine((string)job["data"]["expand"][0]["long_url"]);
}
If jsonString is:
string jsonString = #"{""status_code"": 200, ""status_txt"": ""OK"", ""data"": {""long_url"": ""http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}"", ""url"": ""http:\/\/rlm.cc\/gtYUEd"", ""hash"": ""gtYUEd"", ""global_hash"": ""evz3Za"", ""new_hash"": 0 }}";
the routine will display http://rlm.cc/gtYUEd.
If jsonString is:
string jsonString = #"{""status_code"": 200, ""status_txt"": ""OK"", ""data"": { ""expand"": [ { ""short_url"": ""http:\/\/rlm.cc\/gtYUEd"", ""long_url"": ""http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}"", ""user_hash"": ""gtYUEd"", ""global_hash"": ""evz3Za"" } ] } }";
the routine will display http://panel.aspnix.com/Default.aspx?pid={Removed}.
Not sure I got your problem. Why aren't you testing, if you got a shortening result or a expanding result? Since they are different, this could easily be done via simple 'if ()' statements:
if (results2.ContainsKey("expand")) {
// handle the expand part
} else {
// handle the shorten part
}
Assuming that the provider is consistent with which form it sends, do you need to have code that handles both? It should be direct to handle each individually.
If you can't know ahead of time which format you will get back, you can do the following:
if (results2.ContainsKey("expand"))
{
//Second example
}
else
{
//First example
}