How to create correct struct for json - json

how to parse json correctly I have the following json file
{
"hello": {
"title": "Golang",
"story": [
"Go lang story",
"Channel story"
],
"options": [
{
"text": "That story",
"arc": "west"
},
{
"text": "Gee",
"arc": "east"
}
]
},
"world": {
"title": "Visiting",
"story": [
"Boo",
"Doo",
"Moo",
"Qoo"
],
"options": [
{
"text": "weird",
"arc": "west"
},
{
"text": "funny",
"arc": "north"
}
]
}
}
I've created these structs for the inner part
type chapter struct{
Title string `json:"title"`
Story []string `json:"story"`
Option []option `json:"options"`
}
type option struct {
Text string `json:"text"`
Arc string `json:"arc"`
}
but I don't know how to parse wrappers like "hello" and "world"

All you need to do structuring the root map.
{
"hello":{},
"world":{}
}
Here the hello and world is also inside a map. So you need to structure them too.
var root map[string]chapter
json.Unmarshal(JSONDATA,&root)
Playground example: https://play.golang.org/p/VZ9Bn215dDW

Related

Parsing Iterative JSON from Firebase to Flutter

I have data saved into Realtime Firebase as an iterative JSON as shown in the picture.
Realtime Firebase data
[
{
"name": "Math",
"subMenu": [
{
"name": "Math1",
"subMenu": [
{
"name": "Math 1.1"
},
{
"name": "Math 1.2",
"subMenu": [
{
"name": "Math 1.2.1",
"subMenu": [
{
"name": "Math 1.2.1.1"
},
{
"name": "Math 1.2.1.2"
}
]
},
{
"name": "Math 1.2.2"
}
]
}
]
},
{
"name": "Math2"
},
{
"name": "Math3",
"subMenu": [
{
"name": "Math 1.3.1"
},
{
"name": "Math 1.3.2"
}
]
}
]
},
{
"name": "Marketing",
"subMenu": [
{
"name": "Promotions",
"subMenu": [
{
"name": "Catalog Price Rule"
},
{
"name": "Cart Price Rules"
}
]
},
{
"name": "Communications",
"subMenu": [
{
"name": "Newsletter Subscribers"
}
]
}
]
}
]
How the JSON look like in Realtime Firebase
'Click the image'
datamodel.dart
class Menu {
String? name;
int? font;
List<Menu>? subMenu = [];
Menu({this.name, this.subMenu, this.font});
Menu.fromJson(Map<String, dynamic> json) {
font = json['font'];
name = json['name'];
if (json['subMenu'] != null) {
json['subMenu'].forEach((v) {
subMenu?.add(Menu.fromJson(v));
});
}
}
}
My goal is to build a multilevel list view in Flutter that reflexes iterative JSON structure. So, I implemented a method that returns List<Menu>, and then pass it to a Futurebuilder to build a multilevel list View.
The method.
final ref = FirebaseDatabase.instance.ref();
Future<List<Menu>> firebaseCalls(DatabaseReference ref) async {
final snapshot = await ref.child('Task').get();
final jsondata = snapshot.value as Map<String, dynamic>;
final list = json.decode(jsondata) as List<dynamic>; // Error Location
return list.map((e) => Menu.fromJson(e)).toList();
}
and I got the following
The Error
error: The argument type 'Map<String, dynamic>' can't be assigned to the parameter type 'String'. (argument_type_not_assignable at [flutter_multilevel_list_from_json] lib\main.dart:28)
tried to change the list type to List<dynamic> but still give me an error.
json.decode() takes a String as input, and you are passing a Map<String,dynamic> into it.
That is your problem, not that you are trying to cast it to a List<dynamic>
May be this will be helpful (jsondata as List).map((e) => Menu.fromJson(e)).toList();

Swift - How to JSONDecode with codable for JSON of nested arrays (where arrays without keys or names as per example given)

I am new to Swift and Codable approach. I have to decode the following JSON structure, through Codable approach in Swift project.
[
[
[
{
"id": "58",
"parentCat": "7",
"catFirstTitle": "freedom to"
},
{
"id": "40",
"parentCat": "5",
"catFirstTitle": "freedom to"
}
],
[
{
"id": "58",
"parentCat": "7",
"catFirstTitle": "freedom to"
},
{
"id": "40",
"parentCat": "5",
"catFirstTitle": "freedom to"
}
]
],
[
[
{
"id": "58",
"parentCat": "7",
"catFirstTitle": "freedom to"
}
]
]
]
I could not find any examples of decoding multi level jsonArrays without key names. Any pointer or example will be a great help to me.
You can create a simple struct:
struct Item: Codable {
let id: String
let parentCat: String
let catFirstTitle: String
}
And decode as a nested array object:
let result = try JSONDecoder().decode([[[Item]]].self, from: jsonData)
Note that the result will be of type [[[Item]]].
You may want to flatten it as well:
let flattened = result.flatMap { $0 }.flatMap { $0 }

map[string] struct inside struct

I have a JSON file that looks like this:
{
"jailbreaks": [
{
"jailbroken": false,
"name": "",
"version": "",
"url": "",
"anleitung": [],
"ios": {
"start": "10.2.1"
},
"caveats": "",
"platforms": []
},
{
"jailbroken": true,
"name": "Yalu102",
"version": "beta 6",
"url": "https://domain-dl.tld",
"anleitung": [
{ "blog": "title", "link": "http://domain.tld/" },
{ "blog": "Test", "link": "http://google.at" }
],
"ios": {
"start": "10.2"
},
"caveats": "some text here",
"platforms": [
"Windows",
"OS X",
"Linux"
]
},
And I create the object to work with like this:
type Jailbreak struct {
Jailbroken bool `json:"jailbroken"`
Name string `json:"name"`
Version string `json:"version"`
URL string `json:"url"`
Anleitung map[string]struct {
Name string `json:"blog"`
Link string `json:"link"`
} `json:"anleitung"`
Firmwares struct {
Start string `json:"start"`
End string `json:"end"`
} `json:"ios"`
Platforms []string `json:"platforms"`
Caveats string `json:"caveats"`
}
When I want to build my go program I get an error, that the JSON file cannot be read. But as soon as I delete the map[string]struct I can compile and run the program without any error and everything works fine.
Am I messing around with something or is there an error in my JSON file?
The json provided is not valid (as the array does not have a closing ] and the top level json object lacks another closing }) so let's assume it's like:
{
"jailbreaks": [
{
"jailbroken": false,
"name": "",
"version": "",
"url": "",
"anleitung": [],
"ios": {
"start": "10.2.1",
"end": ""
},
"platforms": [],
"caveats": ""
},
{
"jailbroken": true,
"name": "Yalu102",
"version": "beta 6",
"url": "https://domain-dl.tld",
"anleitung": [
{
"blog": "title",
"link": "http://domain.tld/"
},
{
"blog": "Test",
"link": "http://google.at"
}
],
"ios": {
"start": "10.2",
"end": ""
},
"platforms": [
"Windows",
"OS X",
"Linux"
],
"caveats": "some text here"
}
]
}
The data structure Jailbreaks (first one), marshals-to/unmarshals-from this json properly:
type Jailbreaks struct {
List []Jailbreak `json:"jailbreaks"`
}
type Jailbreak struct {
Jailbroken bool `json:"jailbroken"`
Name string `json:"name"`
Version string `json:"version"`
URL string `json:"url"`
Anleitung []struct {
Name string `json:"blog"`
Link string `json:"link"`
} `json:"anleitung"`
Firmwares struct {
Start string `json:"start"`
End string `json:"end"`
} `json:"ios"`
Platforms []string `json:"platforms"`
Caveats string `json:"caveats"`
}
As you see Anleitung is declared as a slice (not a map).
Use omitempty flag for when your "anleitung" is empty in JSON to be consumed. Beware though, when that is the case, your Jailbreak struct won't have an "anleitung" field.
Change your map's json flag to to;
Anleitung map[string]struct {
Name string `json:"blog"`
Link string `json:"link"`
} `json:"anleitung,omitempty"`
Option 2;
I guess you could also use Anleitung map[string]interface{} but that is better for "holding a map of strings to arbitrary data types". In your case the data is not arbitrary but rather, empty I guess. And looks like that is just temporary.
I'd go for option 1, then I'd check if my struct contains any Anleitung data or not before accessing it.

Map json to dart objects

I'm looking for some direction on mapping json to an object. I'm trying to use live data from a web api. When I run the code I get the following error: Class '_LinkedHashMap' has no instance getter 'iterator'.
Here's what I'm trying to do:
import 'package:angular/angular.dart';
import 'dart:convert';
#NgController(
selector: '[movies]',
publishAs: 'ctrl'
)
class MoviesController {
// vars
bool moviesLoaded = false;
String nameToSearch = 'life';
Http _http;
List<MovieBrief> movies = [];
// constructor
MoviesController( Http this._http ) {
_loadData();
}
// functions
void _loadData() {
moviesLoaded = false;
// _http.get('http://www.omdbapi.com/?s=' + nameToSearch)
_http.get('movies_briefs.json')
.then((HttpResponse response) {
for (Map mb in response.data) {
movies.add(new MovieBrief.fromJsonMap(mb));
}
moviesLoaded = true;
},
onError: (Object obj) {
print(obj);
}
);
}
}
class MovieBrief {
String title;
String year;
String imdbId;
String type;
MovieBrief(this.title, this.year, this.imdbId, this.type);
String toJsonString() {
Map data = {"Search": [
{
"Title" : title,
"Year" : year,
"imdbID" : imdbId,
"Type" : type
}]};
return JSON.encode(data);
}
factory MovieBrief.fromJsonMap( Map json ) {
return new MovieBrief( json['Title'], json['Year'], json['imdbID'], json['Type']);
}
}
Here's a sample of the json results returned by the web api:
{
"Search": [
{
"Title": "Life of Pi",
"Year": "2012",
"imdbID": "tt0454876",
"Type": "movie"
},
{
"Title": "Life Is Beautiful",
"Year": "1997",
"imdbID": "tt0118799",
"Type": "movie"
},
{
"Title": "Life of Brian",
"Year": "1979",
"imdbID": "tt0079470",
"Type": "movie"
},
{
"Title": "It's a Wonderful Life",
"Year": "1946",
"imdbID": "tt0038650",
"Type": "movie"
},
{
"Title": "A Bug's Life",
"Year": "1998",
"imdbID": "tt0120623",
"Type": "movie"
},
{
"Title": "A Bug's Life",
"Year": "1998",
"imdbID": "tt0174716",
"Type": "movie"
},
{
"Title": "The Tree of Life",
"Year": "2011",
"imdbID": "tt0478304",
"Type": "movie"
},
{
"Title": "The Life Aquatic with Steve Zissou",
"Year": "2004",
"imdbID": "tt0362270",
"Type": "movie"
},
{
"Title": "Lara Croft Tomb Raider: The Cradle of Life",
"Year": "2003",
"imdbID": "tt0325703",
"Type": "movie"
},
{
"Title": "Dan in Real Life",
"Year": "2007",
"imdbID": "tt0480242",
"Type": "movie"
}
]
}
Have you looked at the json_object package? This parses a json string and creates properties on the resulting object, in your case you would have say film.title, film.year etc. You can store each json_object in a list.
I'm guessing response.data is a map, so you can't iterate on it with a for loop. You need to either use response.data.keys, response.data.values, or use the forEach method on the map, which provides both.
response.data.forEach((key, value) => movies.add(Etc)
As per the other response, something like json_object is also worth looking into, but that's a way of avoiding hard coding the field mappings.

Go structure for unmarshalling a JSON array

So I have some JSON (courtesy of the PetFinder API) that has a JSON array "pet". I want to unmarshal from it, using the "encoding/json" package, a slice of pet structs. What would this kind of structure look like? I can't find any examples of how the unmarshall function handles JSON arrays.
Here's what I was planning to do once I had a proper struct:
pfetch := new(PetsFetcher) // where PetsFetcher is the struct im asking for
err := json.Unmarshal(body, &pfetch)
And here's the json that is in body (in the form of a slice of ascii bytes):
{
"petfinder": {
"lastOffset": {
"$t": 5
},
"pets": {
"pet": [
{
"options": {
"option": [
{
"$t": "altered"
},
{
"$t": "hasShots"
},
{
"$t": "housebroken"
}
]
},
"breeds": {
"breed": {
"$t": "Dachshund"
}
}
},
{
"options": {
"option": {
"$t": "hasShots"
}
},
"breeds": {
"breed": {
"$t": "American Staffordshire Terrier"
}
},
"shelterPetId": {
"$t": "13-0164"
},
"status": {
"$t": "A"
},
"name": {
"$t": "HAUS"
}
}
]
}
}
}
Thanks in advance.
I really have no idea what those $t attributes are doing there in your JSON, so let’s answer your question with a simple example. To unmarshal this JSON:
{
"name": "something",
"options": [
{
"key": "a",
"value": "b"
},
{
"key": "c",
"value": "d"
},
{
"key": "e",
"value": "f"
},
]
}
You need this Data type in Go:
type Option struct {
Key string
Value string
}
type Data struct {
Name string
Options []Option
}
You can unmarshal a javascript array into a slice. The marhsal/unmarshalling rules are described under Marshal in the json package.
To unmarshal keys that look like "$t", you'll have to annotate the struct that it'll unpack into.
For example:
type Option struct {
Property string `json:"$t,omitempty"`
}
It may be that the $t that appear are a mistake, and are supposed to be keys in a dictionary.