Parsing JSON values from media file metadata on OSX - json

This is my very first attempt at Swift 3 and Xcode 8.3.3. I'm trying to parse a JSON metadata extracted from a file through the command-line application Exiftool.
let task = Process()
let filePath = url.path
let etPath = "/usr/local/bin/exiftool"
task.launchPath = etPath
task.arguments = ["-a", "-g1", "-json", filePath]
let pipe = Pipe()
task.standardOutput = pipe
task.launch()
// Get the data
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output = NSString(data: data, encoding: String.Encoding.utf8.rawValue)
let mydata = output?.data(using: String.Encoding.utf8.rawValue)!
do {
let myJson = try JSONSerialization.jsonObject(with: mydata!, options: []) as AnyObject
if let XMPdc = myJson["XMP-dc"] as AnyObject? {
if let creator = XMPdc["Creator"] as! NSArray? {
print(creator)
}
}
} catch let error as NSError {
print(error)
}
The first part of the script works well, allowing me to get the JSON data into the variable myJson. If I print that variable out, I obtain this:
(
{
Composite = {
ImageSize = 100x100;
Megapixels = "0.01";
};
ExifIFD = {
ColorSpace = Uncalibrated;
ExifImageHeight = 100;
ExifImageWidth = 100;
};
ExifTool = {
ExifToolVersion = "10.61";
};
File = {
ExifByteOrder = "Little-endian (Intel, II)";
FileType = TIFF;
FileTypeExtension = tif;
MIMEType = "image/tiff";
};
"ICC-header" = {
CMMFlags = "Not Embedded, Independent";
ColorSpaceData = "RGB ";
ConnectionSpaceIlluminant = "0.9642 1 0.82487";
DeviceAttributes = "Reflective, Glossy, Positive, Color";
DeviceManufacturer = KODA;
DeviceModel = ROMM;
PrimaryPlatform = "Microsoft Corporation";
ProfileCMMType = KCMS;
ProfileClass = "Display Device Profile";
ProfileConnectionSpace = "XYZ ";
ProfileCreator = KODA;
ProfileDateTime = "1998:12:01 18:58:21";
ProfileFileSignature = acsp;
ProfileID = 0;
ProfileVersion = "2.1.0";
RenderingIntent = "Media-Relative Colorimetric";
};
"ICC_Profile" = {
BlueMatrixColumn = "0.03134 9e-05 0.82491";
BlueTRC = "(Binary data 14 bytes, use -b option to extract)";
DeviceMfgDesc = KODAK;
DeviceModelDesc = "Reference Output Medium Metric(ROMM) ";
GreenMatrixColumn = "0.13519 0.71188 0";
GreenTRC = "(Binary data 14 bytes, use -b option to extract)";
MakeAndModel = "(Binary data 40 bytes, use -b option to extract)";
MediaWhitePoint = "0.9642 1 0.82489";
ProfileCopyright = "Copyright (c) Eastman Kodak Company, 1999, all rights reserved.";
ProfileDescription = "ProPhoto RGB";
RedMatrixColumn = "0.79767 0.28804 0";
RedTRC = "(Binary data 14 bytes, use -b option to extract)";
};
IFD0 = {
Artist = Autore;
BitsPerSample = "16 16 16";
Compression = LZW;
ImageDescription = "Creator: Test ; Date: 1900";
ImageHeight = 100;
ImageWidth = 100;
ModifyDate = "2017:08:10 10:58:42";
Orientation = "Horizontal (normal)";
PhotometricInterpretation = RGB;
PlanarConfiguration = Chunky;
ResolutionUnit = inches;
RowsPerStrip = 100;
SamplesPerPixel = 3;
Software = "Adobe Photoshop CC 2015 (Macintosh)";
StripByteCounts = 1037;
StripOffsets = 11450;
SubfileType = "Full-resolution Image";
XResolution = 300;
YCbCrPositioning = "Co-sited";
YResolution = 300;
};
Photoshop = {
DisplayedUnitsX = inches;
DisplayedUnitsY = inches;
GlobalAltitude = 30;
GlobalAngle = 90;
HasRealMergedData = Yes;
IPTCDigest = 00000000000000000000000000000000;
PhotoshopThumbnail = "(Binary data 557 bytes, use -b option to extract)";
PixelAspectRatio = 1;
PrintPosition = "0 0";
PrintScale = 1;
PrintStyle = Centered;
ReaderName = "Adobe Photoshop CC 2015";
SlicesGroupName = "";
"URL_List" = (
);
WriterName = "Adobe Photoshop";
XResolution = 300;
YResolution = 300;
};
"XMP-dc" = {
Creator = Autore;
Description = "Creator: Test ; Date: 1900";
Format = "image/tiff";
Publisher = "-";
Rights = "-";
Subject = "-";
Title = tite;
};
"XMP-pdf" = {
Producer = "-";
};
"XMP-photoshop" = {
ColorMode = RGB;
ICCProfileName = "ProPhoto RGB";
};
"XMP-x" = {
XMPToolkit = "Image::ExifTool 10.53";
};
"XMP-xmp" = {
CreateDate = 1900;
CreatorTool = "Adobe Photoshop CC 2015 (Macintosh)";
MetadataDate = "2017:08:10 10:58:42-04:00";
ModifyDate = "2017:08:10 10:58:42-04:00";
ThumbnailFormat = "-";
ThumbnailImage = "(Binary data 48 bytes, use -b option to extract)";
};
"XMP-xmpRights" = {
Marked = 1;
};
}
)
However, I don't understand how to correctly parse the data in order to store a specific value, let's say the value that corresponds to the object { "XMP-dc" = {Creator = Autore } }, within my variable creator.
What am I doing wrong?

Try to downcast your json and xmp-dc to the dictionary
let myJson = try JSONSerialization.jsonObject(with: mydata!, options: []) as? [String: Any]
if let XMPdc = myJson?["XMP-dc"] as? [String: Any?] {
//print that dictionary to be sure that al is correct
print(XMPdc)
//I'm not sure that the value Creator is an Array, honestly I don't understand what is the type of that object, but anyway, few fixes for your code
if let creator = XMPdc["Creator"] as? NSArray {
print(creator)
}
}
Again, I'm not sure about the type of the variable Creator, but at least you will know this when you will make print(XMPdc), then you can change the downcast for the creator to the String or whatever.
Let me know if you need something

Related

Extension Autodesk Forge: My control panel doesn't connect to the Revit model after adding my own extension to the package

I used this package (https://github.com/petrbroz/forge-iot-extensions-demo). After that, I added my own extension code (RobotExt.js). The Control panel and Icon of the my extension were added to the Autodesk Forge website. But unfortunately, the control panel doesn't work.
There are these errors:
This is the source code of the my extension file:
class RobotExtension extends Autodesk.Viewing.Extension {
constructor(viewer, options) {
super(viewer, options);
this.viewer = viewer;
//this.tree = null;
this.tree = this.viewer.model.getData().instanceTree;
this.defaultState = null;
this.customize = this.customize.bind(this);
this.createUI = this.createUI.bind(this);
this.setTransformation = this.setTransformation.bind(this);
this.getFragmentWorldMatrixByNodeId = this.getFragmentWorldMatrixByNodeId.bind(this);
this.assignTransformations = this.assignTransformations.bind(this);
this.findNodeIdbyName = this.findNodeIdbyName.bind(this);
}
load() {
console.log('RobotExtension is loaded!');
this.createUI();
this.setTransformation();
return true;
}
unload() {
console.log('RobotExtension is now unloaded!');
this.viewer.restoreState(this.defaultState);
return true;
}
setTransformation() {
let tree = this.tree;
/* ====================== right 0 ================= */
let ID_BaseRod = 4806;
let ID_LowerArmBody = 4806;
let Pivot_BaseRod = new THREE.Mesh(new THREE.BoxGeometry(20, 20, 20), new THREE.MeshBasicMaterial({ color: 0xff0000 }));
let Position_BaseRod = this.getFragmentWorldMatrixByNodeId(ID_BaseRod).matrix[0].getPosition().clone();
//print the returned value from getFragmentWorldMatrixByNodeId method and using this we can inspect the....
// output of the fucntion(method) whether working or not
console.log(Position_BaseRod);
//console.log(position);
Pivot_BaseRod.position.x = 0;
Pivot_BaseRod.position.y = Position_BaseRod.y;
Pivot_BaseRod.position.z = Position_BaseRod.z-2.84;
viewer.impl.scene.add(Pivot_BaseRod);
let Helper_LowerArmBody = new THREE.Mesh();
let Position_LowerArmBody = this.getFragmentWorldMatrixByNodeId(ID_LowerArmBody).matrix[0].getPosition().clone();
Helper_LowerArmBody.position.x = - Position_LowerArmBody.x + Math.abs(Position_LowerArmBody.x - Pivot_BaseRod.position.x);
Helper_LowerArmBody.position.y = - Position_LowerArmBody.y + Math.abs(Position_LowerArmBody.y - Pivot_BaseRod.position.y);
Helper_LowerArmBody.position.z = - Position_LowerArmBody.z + Math.abs(Position_LowerArmBody.z - Pivot_BaseRod.position.z);
Pivot_BaseRod.add(Helper_LowerArmBody);
console.log(Position_LowerArmBody);
// // /* ====================== left 0 ================= */
let ID_BaseRod10 = 4851;
let ID_LowerArmBody10 = 4851;
let Pivot_BaseRod10 = new THREE.Mesh(new THREE.BoxGeometry(0.1, 0.1, 0.1), new THREE.MeshBasicMaterial({ color: 0xff0000 }));
let Position_BaseRod10 = this.getFragmentWorldMatrixByNodeId(ID_BaseRod10).matrix[0].getPosition().clone();
//print the returned value from getFragmentWorldMatrixByNodeId method and using this we can inspect the....
// output of the fucntion(method) whether working or not
console.log(Position_BaseRod10);
Pivot_BaseRod10.position.x = 0;
Pivot_BaseRod10.position.y = Position_BaseRod10.y;
Pivot_BaseRod10.position.z = Position_BaseRod10.z-2.84;
viewer.impl.scene.add(Pivot_BaseRod10);
console.log(Pivot_BaseRod10);
let Helper_LowerArmBody10 = new THREE.Mesh();
let Position_LowerArmBody10 = this.getFragmentWorldMatrixByNodeId(ID_LowerArmBody10).matrix[0].getPosition().clone();
Helper_LowerArmBody10.position.x = Position_LowerArmBody10.x + Math.abs(Position_LowerArmBody10.x - Pivot_BaseRod10.position.x);
Helper_LowerArmBody10.position.y = -Position_LowerArmBody10.y + Math.abs(Position_LowerArmBody10.y - Pivot_BaseRod10.position.y);
Helper_LowerArmBody10.position.z = -Position_LowerArmBody10.z + Math.abs(Position_LowerArmBody10.z - Pivot_BaseRod10.position.z);
Pivot_BaseRod10.add(Helper_LowerArmBody10);
console.log(Position_LowerArmBody10);
let ID_BaseRod15 = 4886;
let ID_LowerArmBody15 = 4886;
let Pivot_BaseRod15= new THREE.Mesh(new THREE.BoxGeometry(0.1, 0.1, 0.1), new THREE.MeshBasicMaterial({ color: 0xff0000 }));
let Position_BaseRod15 = this.getFragmentWorldMatrixByNodeId(ID_BaseRod15).matrix[0].getPosition().clone();
//print the returned value from getFragmentWorldMatrixByNodeId method and using this we can inspect the....
// output of the fucntion(method) whether working or not
console.log(Position_BaseRod15);
Pivot_BaseRod15.position.x = 0;
Pivot_BaseRod15.position.y = Position_BaseRod15.y;
Pivot_BaseRod15.position.z = Position_BaseRod15.z-2.84;
viewer.impl.scene.add(Pivot_BaseRod15);
console.log(Pivot_BaseRod15);
let Helper_LowerArmBody15 = new THREE.Mesh();
let Position_LowerArmBody15 = this.getFragmentWorldMatrixByNodeId(ID_LowerArmBody15).matrix[0].getPosition().clone();
Helper_LowerArmBody15.position.x = Position_LowerArmBody15.x + Math.abs(Position_LowerArmBody15.x - Pivot_BaseRod15.position.x);
Helper_LowerArmBody15.position.y = -Position_LowerArmBody15.y + Math.abs(Position_LowerArmBody15.y - Pivot_BaseRod15.position.y);
Helper_LowerArmBody15.position.z = -Position_LowerArmBody15.z + Math.abs(Position_LowerArmBody15.z - Pivot_BaseRod15.position.z);
Pivot_BaseRod15.add(Helper_LowerArmBody15);
console.log(Position_LowerArmBody15);
There was an error for limitation character in Stackoverflow I had to delete some parts of my code.
[![enter image description here][2]][2]
In the setTransformation method of your extension class, you have the following line of code:
viewer.impl.scene.add(Pivot_BaseRod1);
The viewer variable is not defined, however. The line of code should instead look like this:
this.viewer.impl.scene.add(Pivot_BaseRod1);

Get array item by 1-indexed value in another field

The Firefox file sessionstore-backups/recovery.jsonlz4 contains information about the current Firefox windows in (compressed) JSON format. This is a simplified format representative of that file:
{
"index": 2,
"entries": [
{
"title": "Foo bar 0",
"url": "https://example.com/bar"
},
{
"title": "Foo bar 1",
"url": "https://example.com/bar"
},
{
"title": "Foo bar 2",
"url": "https://example.com/bar"
}
]
}
The index field represents the currently-displayed history item per tab. Being 1-indexed, in the example above it represents the "Foo bar 1" entry.
How can I use that value in jq to get that tab?
For testing on your own system, the following bash line will get you to this point on most modern Linux systems:
lz4jsoncat ~/.mozilla/firefox/t6e99qbe.default-release/sessionstore-backups/recovery.jsonlz4 | jq '.windows[0].tabs' | jq 'sort_by(.lastAccessed)[-1]'
This returns the most recent tab, but with all history items in the entries array. As the user could have navigated back in the history, we need the index value to determine which entry to return. Piped through gron, it looks like this:
json = {};
json.attributes = {};
json.entries = [];
json.entries[0] = {};
json.entries[0].ID = 504;
json.entries[0].cacheKey = 0;
json.entries[0].docIdentifier = 586;
json.entries[0].docshellUUID = "{b6c1e18a-d0f5-4ba2-996e-ddd9fc28322a}";
json.entries[0].hasUserInteraction = true;
json.entries[0].persist = true;
json.entries[0].principalToInherit_base64 = "eyIxIjp7IjAiOiJtb3otZXh0ZW5zaW9uOi8vOTAzYWU2NDgtMzRlNi00NGQ3LTg0NjYtYzgxMWQyMTg2YjBkLyJ9fQ==";
json.entries[0].resultPrincipalURI = null;
json.entries[0].title = "Tridactyl Top Tips & New Tab Page";
json.entries[0].triggeringPrincipal_base64 = "eyIxIjp7IjAiOiJtb3otZXh0ZW5zaW9uOi8vOTAzYWU2NDgtMzRlNi00NGQ3LTg0NjYtYzgxMWQyMTg2YjBkLyJ9fQ==";
json.entries[0].url = "moz-extension://7ba85bcd-8d63-4e74-a723-e627a31d6274/static/newtab.html";
json.entries[1] = {};
json.entries[1].ID = 506;
json.entries[1].cacheKey = 0;
json.entries[1].docIdentifier = 588;
json.entries[1].docshellUUID = "{b6c1e18a-d0f5-4ba2-996e-ddd9fc28322a}";
json.entries[1].hasUserInteraction = true;
json.entries[1].persist = true;
json.entries[1].referrerInfo = "BBoSnxDOS9qmDeAnom1e0AAAAAAAAAAAwAAAAAAAAEYAAAAAAAEBAAAAAAEA";
json.entries[1].resultPrincipalURI = null;
json.entries[1].title = "Stack Overflow - Where Developers Learn, Share, & Build Careers";
json.entries[1].triggeringPrincipal_base64 = "eyIzIjp7fX0=";
json.entries[1].url = "https://stackoverflow.com/";
json.entries[2] = {};
json.entries[2].ID = 508;
json.entries[2].cacheKey = 0;
json.entries[2].csp = "CdntGuXUQAS/4CfOuSPZrAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAGmh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vAAAAAAAAAAUAAAAIAAAAEQAAAAj/////AAAACP////8AAAAIAAAAEQAAABkAAAABAAAAGQAAAAEAAAAZAAAAAQAAABoAAAAAAAAAGv////8AAAAA/////wAAABn/////AAAAGf////8BAAAAAAAAAAAAKHsiMSI6eyIwIjoiaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS8ifX0AAAABAAAASwB1AHAAZwByAGEAZABlAC0AaQBuAHMAZQBjAHUAcgBlAC0AcgBlAHEAdQBlAHMAdABzADsAIABmAHIAYQBtAGUALQBhAG4AYwBlAHMAdABvAHIAcwAgACcAcwBlAGwAZgAnACAAaAB0AHQAcABzADoALwAvAHMAdABhAGMAawBlAHgAYwBoAGEAbgBnAGUALgBjAG8AbQAA";
json.entries[2].docIdentifier = 590;
json.entries[2].docshellUUID = "{b6c1e18a-d0f5-4ba2-996e-ddd9fc28322a}";
json.entries[2].hasUserInteraction = true;
json.entries[2].persist = true;
json.entries[2].principalToInherit_base64 = "eyIxIjp7IjAiOiJodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tLyJ9fQ==";
json.entries[2].referrerInfo = "BBoSnxDOS9qmDeAnom1e0AAAAAAAAAAAwAAAAAAAAEYBAAAAGmh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vAAAACAEBAAAAGmh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vAQE=";
json.entries[2].resultPrincipalURI = null;
json.entries[2].title = "Highest scored questions - Stack Overflow";
json.entries[2].triggeringPrincipal_base64 = "eyIxIjp7IjAiOiJodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tLyJ9fQ==";
json.entries[2].url = "https://stackoverflow.com/questions";
json.entries[3] = {};
json.entries[3].ID = 510;
json.entries[3].cacheKey = 0;
json.entries[3].csp = "CdntGuXUQAS/4CfOuSPZrAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAI2h0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zAAAAAAAAAAUAAAAIAAAAEQAAAAj/////AAAACP////8AAAAIAAAAEQAAABkAAAAKAAAAGQAAAAoAAAAZAAAAAQAAABoAAAAJAAAAGv////8AAAAA/////wAAABn/////AAAAGf////8BAAAAAAAAAAAAMXsiMSI6eyIwIjoiaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMifX0AAAABAAAASwB1AHAAZwByAGEAZABlAC0AaQBuAHMAZQBjAHUAcgBlAC0AcgBlAHEAdQBlAHMAdABzADsAIABmAHIAYQBtAGUALQBhAG4AYwBlAHMAdABvAHIAcwAgACcAcwBlAGwAZgAnACAAaAB0AHQAcABzADoALwAvAHMAdABhAGMAawBlAHgAYwBoAGEAbgBnAGUALgBjAG8AbQAA";
json.entries[3].docIdentifier = 592;
json.entries[3].docshellUUID = "{b6c1e18a-d0f5-4ba2-996e-ddd9fc28322a}";
json.entries[3].hasUserInteraction = true;
json.entries[3].persist = true;
json.entries[3].principalToInherit_base64 = "eyIxIjp7IjAiOiJodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucyJ9fQ==";
json.entries[3].referrerInfo = "BBoSnxDOS9qmDeAnom1e0AAAAAAAAAAAwAAAAAAAAEYBAAAAI2h0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zAAAACAEBAAAAI2h0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zAQE=";
json.entries[3].resultPrincipalURI = null;
json.entries[3].title = "Tags - Stack Overflow";
json.entries[3].triggeringPrincipal_base64 = "eyIxIjp7IjAiOiJodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucyJ9fQ==";
json.entries[3].url = "https://stackoverflow.com/tags";
json.entries[4] = {};
json.entries[4].ID = 512;
json.entries[4].cacheKey = 0;
json.entries[4].csp = "CdntGuXUQAS/4CfOuSPZrAAAAAAAAAAAwAAAAAAAAEYB3pRy0IA0EdOTmQAQS6D9QJIHOlRteE8wkTq4cYEyCMYAAAAC/////wAAAbsBAAAAHmh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vdGFncwAAAAAAAAAFAAAACAAAABEAAAAI/////wAAAAj/////AAAACAAAABEAAAAZAAAABQAAABkAAAAFAAAAGQAAAAEAAAAaAAAABAAAABr/////AAAAAP////8AAAAZ/////wAAABn/////AQAAAAAAAAAAACx7IjEiOnsiMCI6Imh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vdGFncyJ9fQAAAAEAAABLAHUAcABnAHIAYQBkAGUALQBpAG4AcwBlAGMAdQByAGUALQByAGUAcQB1AGUAcwB0AHMAOwAgAGYAcgBhAG0AZQAtAGEAbgBjAGUAcwB0AG8AcgBzACAAJwBzAGUAbABmACcAIABoAHQAdABwAHMAOgAvAC8AcwB0AGEAYwBrAGUAeABjAGgAYQBuAGcAZQAuAGMAbwBtAAA=";
json.entries[4].docIdentifier = 594;
json.entries[4].docshellUUID = "{b6c1e18a-d0f5-4ba2-996e-ddd9fc28322a}";
json.entries[4].hasUserInteraction = false;
json.entries[4].persist = true;
json.entries[4].principalToInherit_base64 = "eyIxIjp7IjAiOiJodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3RhZ3MifX0=";
json.entries[4].referrerInfo = "BBoSnxDOS9qmDeAnom1e0AAAAAAAAAAAwAAAAAAAAEYBAAAAHmh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vdGFncwAAAAgBAQAAAB5odHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3RhZ3MBAQ==";
json.entries[4].resultPrincipalURI = null;
json.entries[4].title = "Users - Stack Overflow";
json.entries[4].triggeringPrincipal_base64 = "eyIxIjp7IjAiOiJodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3RhZ3MifX0=";
json.entries[4].url = "https://stackoverflow.com/users";
json.hidden = false;
json.index = 3;
json.lastAccessed = 1651407567904;
json.requestedIndex = 0;
json.searchMode = null;
json.userContextId = 0
Just index entries by index minus one?
.entries[.index - 1]
Online demo
The last item in entries is not necessarily the tab that was opened. [.index - 1] only works if user_pref("browser.sessionstore.max_serialize_forward", 0); cf. https://wiki.mozilla.org/Firefox/session_restore#Browser_settings

Javascript Base64 Decoding to Invalid JSON Output

I'm using a Firebase Cloud function to receive a JSON payload in an http request from the App Store (server-to-server notifications) that contains a Base64 encoded string. I'm decoding using:
const latestReceipt = request.body.latest_receipt ? Buffer.from(request.body.latest_receipt, 'base64').toString() : null;
This is works fine in another function to decode a message coming from the Google Play Store. The decoded string coming from Apple, however, is an invalid JSON object.
{
"original-purchase-date-pst" = "2019-09-20 16:40:20 America/Los_Angeles";
"quantity" = "1";
"subscription-group-identifier" = "****";
"unique-vendor-identifier" = "****";
"original-purchase-date-ms" = "1569022820000";
"expires-date-formatted" = "2019-09-24 02:55:47 Etc/GMT";
"is-in-intro-offer-period" = "false";
"purchase-date-ms" = "1569293447000";
"expires-date-formatted-pst" = "2019-09-23 19:55:47 America/Los_Angeles";
"is-trial-period" = "false";
"item-id" = "1478806339";
"unique-identifier" = "******";
"original-transaction-id" = "1000000570864027";
"expires-date" = "1569293747000";
"transaction-id" = "1000000571530192";
"bvrs" = "11";
"web-order-line-item-id" = "1000000047099385";
"version-external-identifier" = "0";
"bid" = "****";
"product-id" = "storage_increase";
"purchase-date" = "2019-09-24 02:50:47 Etc/GMT";
"purchase-date-pst" = "2019-09-23 19:50:47 America/Los_Angeles";
"original-purchase-date" = "2019-09-20 23:40:20 Etc/GMT";
}
I'm assuming that I'm doing something wrong, but I'm not sure what exactly. I wouldn't expect the App Store to send invalid JSON.

JSON bug of data fromlocalStorage and string

Is it bug or my fault?
Variable from string and from localStorage behave differently.
var colors ="", colors2 ="", getColor = "";
var defaultColorScheme = '{"asideBackgroud":"#fff", "asideColor":"#000", "sectionBackgroud":"#eee", "sectionColor":"#111"}';
if (!localStorage.colorScheme) {
localStorage.setItem('colorScheme', JSON.stringify(defaultColorScheme));
}
getColor = localStorage.getItem('colorScheme');
colors = JSON.parse(getColor); // from loc. storage
colors2 = JSON.parse(defaultColorScheme); // string
alert (colors.asideBackgroud+" -- "+ colors2.asideBackgroud);
if (defaultColorScheme === colors) {
alert("yes");
}
//localStorage.clear();

how to hide Empty UITableViewcell Label with using json?

hi i need to hide empty UITableViewcell label in custom TableView.i am trying to display JSON webservice values in custom tableviewcell.
my json vales are looks like ...
(
{
post = {
"CLASS_LEVEL" = "Intro/General";
"CLASS_TYPE" = "Muay Thai";
"DAY_OF_WEEK" = "";
ID = 19;
"ORDER_BY" = 5;
TIME = "1:00pm - 2:30pm";
};
}
{
post = {
"CLASS_LEVEL" = "General/Intermediate/Advanced";
"CLASS_TYPE" = "Muay Thai Spar - Competitive";
"DAY_OF_WEEK" = "";
ID = "";
"ORDER_BY" = 5;
TIME = "6:00pm - 9:00pm";
};
},
{
post = {
"CLASS_LEVEL" = "Fighters/Advanced/Intermediate";
"CLASS_TYPE" = "Fighters Training";
"DAY_OF_WEEK" = Monday;
ID = 1;
"ORDER_BY" = 1;
TIME = "";
};
},
i need to auto size my table cell dynamically .
here some of values are empty that values assigned label in tableviewcell want to be hidden.
is it possible? help me .Thanks in advance
To hide the UILabel you can just do cell.label.hidden = YES;
You can try this
NSString *dayOfWeek = ... ;
if(dayOfWeek == (id) [NSNull null] || [dayOfWeek length] == 0 || [dayOfWeek isEqualToString:#""])
{
cell.label.hidden = YES;
}
else
{
cell.label.hidden = NO;
}