In Swift how to decode API keys that are Pascal Case? [duplicate] - json

This question already has answers here:
How do I use custom keys with Swift 4's Decodable protocol?
(4 answers)
Decode a PascalCase JSON with JSONDecoder
(1 answer)
Closed 3 months ago.
I can easily decode the keys that are Camel Case:
struct TheData: Codable {
let theNumber: Float
}
But I can not decode this version:
struct TheData: Codable {
let TheNumber: Float
}
"TheNumber" is with first letter capitalized and Swift does allow constants starting with capital case. I have tried to lower case the first letter but it didn't work.

Here is the solution:
struct TheData: Codable {
let theNumber: Float
private enum CodingKeys: String, CodingKey {
case theNumber = "TheNumber"
}
}
It is mentioned in: How do I use custom keys with Swift 4's Decodable protocol?

Related

(Rust) What's an ergonomic way to serialize nested structs containing JSON data using Arc<RwLock<>>? [duplicate]

This question already has answers here:
How to deserialize a parking_lot::Mutex with Serde?
(1 answer)
How do I serialize or deserialize an Arc<T> in Serde?
(1 answer)
Closed 7 months ago.
Disclaimer: This is my first SO post, so forgive me if I fail to comply to convention
I've got some musical artist streaming analytics data and I am trying to use it on my first Rust-based personal project. I would like to take the data (already formatted in JSON) and graph it within a web-app. My artist data structure takes the form
#[derive(Clone, Debug)]
struct Artist {
genre: genre::Genre,
socials: Vec<String>,
background: Arc<RwLock<Background>>,
soundcloud_data: Arc<RwLock<serde_json::value::Value>>,
...
spotify_data: Arc<RwLock<serde_json::value::Value>>,
}
#[derive(Clone, Debug)]
struct Background {
origin: Arc<RwLock<Origin>>,
description: String,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
struct Origin{
city: String,
state: String,
country: String,
}
Later on I collect a number of various "Artist" instances into a Vec ("result"), and try to return a reference to said Vec:
Ok(warp::reply::json(&result))
But the issue is that "the trait bound 'Artist: Serialize' is not satisfied..." I am unable to derive serialize for Arc<RwLock> because of the Orphan Rule (note, I'm using the Parking_lot's async implementation of RwLock).
I've began trying to implement Serialize for Artist and Background, but I wonder what's the best way to go about this?
Do I need to replace
Arc<RwLock<serde_json::value::Value>>
with
Arc<RwLock<descriptive_struct>>
where descriptive_struct has the (nested) structure of the JSON file? Then implement serialize for said struct? Or is there a better way to do this that I'm not seeing?

Decode nested JSON child with Decodable [duplicate]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
The new Swift "Decoder" class sounds like a great way to parse JSON data, but all of the examples I've found use a well-known, well-defined 'struct' to do so.
In my case I'm querying an arbitrary website that returns a HUGE JSON string and I only care about a few of the (deeply nested) fields, so I don't want to take all that time to define a 'struct' to get at them.
Is it even possible to do this with "Decoder"? And if so, how does one go about it?
The question seems to be based on a misapprehension about how Decodable works. As a convenience, Decodable is willing to do some automatic code generation behind the scenes so that you can define a struct or nest of structs and just decode the entirety of the JSON. But you are not required to take advantage of that in order to decode JSON.
There is no need to define struct properties for "fields" you don't care about. If a JSON dictionary contains 100 keys and your corresponding struct contains just one property, no problem; that key will be fetched, and no others.
With regard to the "deeply nested" part, it should not take you much time to write simple nested structs that perform the dive to reach the dictionary you really care about. But if you don't want to do even that, you could write an implementation of init(from:) that dives down and fetches out the desired values.
In other words, if you think of Decodable as consisting primarily of your implementation of init(from:), and learn to write the code that it needs, you will see that this JSON can be parsed in a few quick simple lines of code.
As an example, here's a JSON sketch of a deeply nested piece of information with a bunch of extra information at every level that we want to ignore:
{
"ignore": true,
"outer1": {
"ignore": true,
"outer2": {
"ignore": true,
"outer3": {
"name": "matt",
"ignore": true
}
}
}
}
What I'd like to do is define a very simple struct Person that consists solely of the deeply nested name:
struct Person : Decodable {
let name : String
}
I can do that! To do so, I implement Decodable myself, supplying a "hoover" CodingKey adopter struct and an implementation of init(from:), like this (this may look like a lot of work, but it isn't, because the AnyCodingKey implementation is boilerplate, copied and pasted from here, and the init(coder:) implementation is just a few lines of code that were easy to write):
struct Person : Decodable {
let name : String
struct AnyCodingKey : CodingKey {
var stringValue: String
var intValue: Int?
init(_ codingKey: CodingKey) {
self.stringValue = codingKey.stringValue
self.intValue = codingKey.intValue
}
init(stringValue: String) {
self.stringValue = stringValue
self.intValue = nil
}
init(intValue: Int) {
self.stringValue = String(intValue)
self.intValue = intValue
}
}
init(from decoder: Decoder) throws {
var con = try! decoder.container(keyedBy: AnyCodingKey.self)
con = try! con.nestedContainer(keyedBy: AnyCodingKey.self, forKey: AnyCodingKey(stringValue:"outer1"))
con = try! con.nestedContainer(keyedBy: AnyCodingKey.self, forKey: AnyCodingKey(stringValue:"outer2"))
con = try! con.nestedContainer(keyedBy: AnyCodingKey.self, forKey: AnyCodingKey(stringValue:"outer3"))
let name = try! con.decode(String.self, forKey: AnyCodingKey(stringValue:"name"))
self.name = name
}
}
When I want to dive into the JSON and grab the name information, it's trivial:
let person = try! JSONDecoder().decode(Person.self, from: json)
The result is a Person object with name value "matt". Note that I didn't have to add any of the ignore keys and I didn't need to make a nest of structs.
Sure you can achieve this but with both JSonSerialization & Decodable , you have to serialize the json until reach the desired content then decode it ,but instead I recommend to create structs for root keys only then decode , think of it as it's a path from top to bottom don't decode a key that isn't in the path of your desired content

Swift 5 JSONDecoder decode JSON with field name having a space eg "post title": "Hello World" [duplicate]

This question already has answers here:
How do I use custom keys with Swift 4's Decodable protocol?
(4 answers)
Closed 3 years ago.
I'm currently using JSONDecoder to parse json into objects with Swift 5. I'm just realizing now that part of the JSON is bad JSON. It has a field name with a space: "Post Title". I'm not sure why it is like this, and I'm aware it is bad practice for JSON to be setup like this, but there's not much I can do on the JSON side. Is there a way to use JSON decoder to get that field as is?
I've researched this a ton, but since it is an issue with bad json, I'm not finding much online other than creating a custom decoder/deserializer (which I'm trying to avoid).
JSON:
{
"Post Title":"Hello World"
}
Struct:
struct Post: Decodable {
var PostTitle: String
}
Decoder:
let jsonObject = try jsonDecoder.decode(Post.self, from: responseData)
Thank you in advance!
For custom keys, use CodingKeys to match JSON keys.
struct Post : Codable {
var PostTitle: String
private enum CodingKeys : String, CodingKey {
case PostTitle = "Post Title"
}
}
Note: you should use lowercased starting letter for variables.

Use "/" and "%" in Codable - Swift [duplicate]

This question already has answers here:
How do I use custom keys with Swift 4's Decodable protocol?
(4 answers)
Closed 4 years ago.
I use an API to parse some data - this works. But now the api uses names like "d/a" and "test%" and I can't create a codable struct with this symbols. Is there a way to use them?
Thanks in advance
You can remap your keys. Here is a basic example:
struct MyObject: Codable {
var name: String
var da: String
var test: String
enum CodingKeys: String, CodingKey {
case name
case da = "d/a"
case test = "test%"
}
}
You can read more about it in the documentation here
Keep in mind though that you will have to manually include all the properties that you want to be encoded/decoded and that "The names of the enumeration cases should match the names you've given to the corresponding properties in your type"

Golang Struct Won't Marshal to JSON [duplicate]

This question already has answers here:
My structures are not marshalling into json [duplicate]
(3 answers)
Closed 7 years ago.
I'm trying to marshal a struct in Go to JSON but it won't marshal and I can't understand why.
My struct definitions
type PodsCondensed struct {
pods []PodCondensed `json:"pods"`
}
func (p *PodsCondensed) AddPod(pod PodCondensed) {
p.pods = append(p.pods, pod)
}
type PodCondensed struct {
name string `json:"name"`
colors []string `json:"colors"`
}
Creating and marshaling a test struct
fake_pods := PodsCondensed{}
fake_pod := PodCondensed {
name: "tier2",
colors: []string{"blue", "green"},
}
fake_pods.AddPod(fake_pod)
fmt.Println(fake_pods.pods)
jPods, _ := json.Marshal(fake_pods)
fmt.Println(string(jPods))
Output
[{tier2 [blue green]}]
{}
I'm not sure what the issue is here, I export json data for all my structs, the data is being stored correctly and is available to print. It just wont marshal which is odd because everything contained in the struct can be marshaled to JSON on its own.
This is a common mistake: you did not export values in the PodsCondensed and PodCondensed structures, so the json package was not able to use it. Use a capital letter in the variable name to do so:
type PodsCondensed struct {
Pods []PodCondensed `json:"pods"`
}
type PodCondensed struct {
Name string `json:"name"`
Colors []string `json:"colors"`
}
Working example: http://play.golang.org/p/Lg3cTO7DVk
Documentation: http://golang.org/pkg/encoding/json/#Marshal