Deserialize JSON using JSON.net in Wp7 application - json

I have this JSON format:
string jsonFormat = #"{
""Applications"": {
""data"": {
""Application named one"": [
{
""index"" : ""1"",
""name"" : ""One"",
""active"" : ""1"",
""excluded"" : ""false""
}
],
""Application named two"": [
{
""index"" : ""2"",
""forum"" : ""yes"",
}
]
}
}
}";
How exactly I can acces data childrens ? I need to retreive Application named one and Application named two - for each also the attributes with their values - the attributes are different from Application to Application.
Untill now I have:
JObject resultt= JObject.Parse(jsonFormat);
// get JSON result objects into a list
IList<JToken> results = resultt["Applications"]["data"].Children().ToList();
I looked over JSON.net documentation and could not find a solution for this...
Any help will be very usefull. Thank you.

I think you are looking for something like this:
JObject jObject = JObject.Parse(jsonFormat);
int index = jObject
.Value<JObject>("Applications")
.Value<JObject>("data")
.Value<JArray>("Application named one")
.First
.Value<int>("index");
Basically the idea is to use the Value method with the type you are expecting to retrieve a specific json element (JObject, JArray, ...) or parse a .NET value (int, string, bool, ...).

Related

How can I get a deep element of a json string in scala?

I am using Scala to parse json with a structure like this:
{
"root": {
"metadata": {
"name": "Farmer John",
"hasTractor": false
},
"plants": {
"corn": 137.137,
"soy": 0.45
},
"animals": {
"cow": 4,
"sheep": 12,
"pig": 1
}
}
}
And I am currently using the org.json library to parse it, like this:
val jsonObject = new JSONObject(jsonString) // Where jsonString is the above json tree
But when I run something like jsonObject.get("root.metadata.name") then I get the error:
JSONObject["root.metadata.name"] not found.
org.json.JSONException: JSONObject["root.metadata.name"] not found.
I suspect I can get the objects one at a time by splitting up that path, but that sounds tedious and I assume a better json library already exists. Is there a way to easily get the data the way I am trying to or is there a better library to use that works better with Scala?
The JSONObject you are using is deprecated. The deprecation message sends you to The Scala Library Index. I'll demonstrate how this can be done in play-json. Let's assume that the json above is stored at jsonString, so we can do:
val json = Json.parse(jsonString)
val path = JsPath \ "root" \ "metadata" \ "name"
path(json) match {
case Nil =>
??? // path does nont exist
case values =>
println(s"Values are: $values")
}
Code run at Scastie.
Looks like I was able to solve it using JsonPath like this:
val document = Configuration.defaultConfiguration().jsonProvider().parse(jsonString): Object
val value = JsonPath.read(document, "$.root.metadata.name"): Any

Transform string array to integer array during JSON decode using Unbox in Swift

UPDATE: This has now been fixed in Unbox 1.9.
I'm using the awesome Unbox JSON decoder in a small Swift project and so far it has proven very easy to work with. However, I've run into a small problem trying to decode and transform a string array in JSON to an integer array property.
I have a Conversation class that looks like this:
final class Conversation: Unboxable {
var participants: [Int]?
var subject: String?
var timestamp: Int?
var conversationId: String?
init(unboxer: Unboxer) {
self.participants = unboxer.unbox("participants")
self.subject = unboxer.unbox("subject")
self.timestamp = unboxer.unbox("timestamp")
self.conversationId = unboxer.unbox("conversationId")
}
}
The JSON that I'm working with looks like this:
{
"subject" : "subject line goes here",
"participants" : [
"201984",
"237810",
"149092",
"202577"
],
"timestamp" : 1468322845885,
"conversationId" : "9bf356d1-4823-11e6a51e-2d6dfda33d93"
}
As you can see, the participants array in the JSON is a string array and I'd like to transform it into an integer array. When I run my code, the participants property in my class is nil after unboxing. If I change its type to [String]?, then it unboxes ok. One of the nice things about Unbox is that it will automagically transform (where possible) a string value into a numeric type for you. But either I'm doing something wrong or Unbox doesn't provide this same capability for arrays. Has anyone done this using Unbox before?

updating Json object

I have a json object that I need to update. The original object is a list that looks like this:
[
{
"firstName":"Jane",
"lastName":"Smith"
},
{
"firstName":"Jack",
"lastName":"Brown"
}
]
For each element in the list, we have an extra field, "age", that needs to be added at run-time, so the result should look like the following:
[
{
"firstName":"Jane",
"lastName":"Smith",
"age": "21"
},
{
"firstName":"Jack",
"lastName":"Brown",
"age": "34"
}
]
Any suggestions how to do this so the result is still json?
Thanks.
request.body.asJson.map {
jm => (jm.as[JsObject] ++ Json.obj("age" -> 123))
}
I would recommended deserializing the JSON array you receive into a List of case classes, then having some function fill in the missing attributes based on the current attributes of the case class, and finally serializing them as JSON and serving the response.
Let's make a Person case class with the fields that will be missing as Option:
import play.api.libs.json.Json
case class Person(firstName: String, lastName: String, age: Option[Int])
object Person {
implicit val format: Format[Person] = Json.format[Person]
def addAge(person: Person): Person = {
val age = ... // however you determine the age
person.copy(age = Some(age))
}
}
Within the companion object for Person I've also defined a JSON serializer/deserializer using the format macro, and a stub for a function that will find a person's age then copy it back into the person and return it.
Deep within the web service call you might then have something like this:
val jsArray = ... // The JsValue from somewhere
jsArray.validate[List[Person]].fold(
// Handle the case for invalid incoming JSON
error => InternalServerError("Received invalid JSON response from remote service."),
// Handle a deserialized array of List[Person]
people => {
Ok(
// Serialize as JSON, requires the implicit `format` defined earlier.
Json.toJson(
// Map each Person to themselves, adding the age
people.map(person => Person.addAge(person))
)
)
}
)
This method is much safer, otherwise you'll have to extract values from the array one by one and concatenate objects, which is very awkward. This will also allow you to easily handle errors when the JSON you receive is missing fields you're expecting.

Couchbase - deserialize json into dynamic type

I'm trying to deserialize some JSON coming back from couchbase into a dynamic type.
The document is something like this so creating a POCO for this would be overkill:
{
UsersOnline: 1
}
I figured that something like this would do the trick, but it seems to deserialize into a dynamic object with the value just being the original JSON
var jsonObj = _client.GetJson<dynamic>(storageKey);
results in:
jsonObj { "online": 0 }
Is there anyway I can get the couchbase deserializer to generate the dynamic type for me?
Cheers
The default deserializer for the client uses .NET's binary serializer, so when you save or read a JSON string, it's just a string. GetJson will always just return a string. However, there are a couple of options:
You could convert JSON records to Dictionary instances:
var appJson = "{ \"UsersOnline\" : 1, \"NewestMember\" : \"zblock\" }";
var result = client.ExecuteStore(StoreMode.Set, "userCount", appJson);
var item = client.GetJson<Dictionary<string, object>>("userCount");
Console.WriteLine("There are {0} users online. The newest member is {1}.",
item["UsersOnline"], item["NewestMember"]);
Or you could use a dynamic ExpandoObject instance:
var appJson = "{ \"UsersOnline\" : 1, \"NewestMember\" : \"zblock\" }";
var result = client.ExecuteStore(StoreMode.Set, "userCount", appJson);
dynamic item = client.GetJson<ExpandoObject>("userCount");
Console.WriteLine("There are {0} users online. The newest member is {1}.",
item.UsersOnline, item.NewestMember);
In either case you're losing static type checking, which seems like it's OK for your purposes. In both cases you get access to the JSON properties without having to parse the JSON into a POCO though...
Edit: I wrote a couple of extension methods that may be useful and blogged about them at http://blog.couchbase.com/moving-no-schema-stack-c-and-dynamic-types

How can you use GWT AutoBeans to parse a JSON message when some of the return values could be an object or a collection of objects?

Is it possible to parse a JSON message using GWT AutoBeans when one of the objects returned may be a collection but not always?
For example, if I have a JSON message returning an author and his/her associated writings, it's possible that there could be zero or more books being returned.
{ "name" : "William Gibson", "books" : { bookname : "Neuromancer" } }
could be one response, but so could this:
{ "name" : "William Gibson", "books" : [ { bookname: "Neuromancer"}, { bookname : "Pattern Recognition" } ] }
When I attempt to model this with an interface to be used for marshalling with an AutoBean, I get "expecting indexed data" errors if only one book is returned.
Interface for the AutoBean:
public interface Author {
#PropertyName(value="name")
String getAuthorName();
#PropertyName(value="book")
List<String> getBooks();
}
Snippet of error:
java.lang.AssertionError: Expecting indexed data
at com.google.web.bindery.autobean.shared.impl.SplittableList.<init>(SplittableList.java:64)
Is this not possible with AutoBeans?
(Note: using GWT 2.5.0 GA)
If you have a List, AutoBeans expects a JSON array. That array could contain zero, one or more elements, but it has to be an array (or be absent).
I think you can make your getBooks method return a Splittable though. You could then know whether it's an array (isIndexed()) or not. If you need the array to contain objects, you'd then have to iterate on the array (size() and get(int)) and pass each element to AutoBeanCodex.decode() to decode them (or directly pass the splittable if it's not an array).