TransWikia.com

How to parse JSON

Mathematica Asked by Joe Blow on May 2, 2021

please forgive me if this is obvious, but I have some JSON:

ExportString[
<|"Names" -> <|
    "Sister" -> "Nina",
    "Brothers" -> {<|"Older" -> "John","Younger" -> "Jake"|>},
    "somethingElse" -> "answer"|>,
  "DOB" -> {<|
        "Nina" -> 2001,
        "location" -> "Miami"|>,
        <|"John" -> 2017,
        "location" -> "Hell"|>}|>, "RawJSON"]

(NOTE, I am converting an association to JSON just for the purposes of this post. In reality I am making a URL request and it is returning JSON).

I want to separate the JSON at depth 1. So I want to return an association of “Names” and an Association of “DOB”. Is there a function similar to Lookup that works with JSON or some other way to index JSON?

Thank you.

EDIT: Actually, I would like to keep “Names” as JSON.

EDIT (per comments): Here’s what i’m looking for structurally:
The first output I want is the JSON corresponding to “Names”:

out1 =
{
"Names":{
    "Sister":"Nina",
    "Brothers":[
        {
            "Older":"John",
            "Younger":"Jake"
        }
    ],
    "somethingElse":"answer"
    }
}

The second output I want is an Association of the values corresponding to “DOB”:

out2 = 
    <|"DOB"->{<|
        "Nina" -> 2001,
        "location" -> "Miami"|>,
        <|"John" -> 2017,
        "location" -> "Hell"|>}|>

3 Answers

The example JSON string:

json = ExportString[<|
    "Names" -> <|
      "Sister" -> "Nina",
      "Brothers" -> {<|"Older" -> "John", "Younger" -> "Jake"|>},
      "somethingElse" -> "answer"
      |>,
    "DOB" -> {
      <|"Nina" -> 2001, "location" -> "Miami"|>,
      <|"John" -> 2017, "location" -> "Hell"|>}
    |>, "RawJSON"];

Import it as an association:

assoc = ImportString[json, "RawJSON"];

Here is how to get an association for each key at the first level:

<|# -> assoc[[#]]|> & /@ Keys[assoc]

Here is how to get a JSON string for each key at the first level:

ExportString[<|# -> assoc[[#]]|>, "JSON"] & /@ Keys[assoc]

Correct answer by C. E. on May 2, 2021

The various approaches I have seen on the web, including above, don't work for my data, which may be more complex than others' test cases or contain some unusual or malformed elements. Anyway, I wrote a bit of recursive code that handles it well. I'm posting it here in case it's of use to others.

list2Assoc[in_] := Which[
   VectorQ[in, Head[#] === Rule &], 
   Apply[Association, Map[list2Assoc, in]],
   ListQ[in], Map[list2Assoc, in],
   Head[in] === Rule && ListQ[in[[2]]], in[[1]] -> list2Assoc[in[[2]]],
   True, in];

This converts the JSON, which has been brought into Mathematica with Import and has a Head of List, into an Association of Associations that is easier to extract elements from.

Answered by Michael Stern on May 2, 2021

Here is another take on this issue. I was importing a nested JSON from an API call from the Homeland Infrastructure Foundation using the call below:

tst = Import["https://services1.arcgis.com/Hp6G80Pky0om7QvQ/arcgis/rest/services/Electric_Power_Transmission_Lines/FeatureServer/0/query?where=1%3D1&outFields=*&geometry=-123.936%2C35.284%2C-90.559%2C41.313&geometryType=esriGeometryEnvelope&inSR=4326&spatialRel=esriSpatialRelIntersects&outSR=4326&f=json", "JSON"];

My approach was to find the List heads that had a rule within them using:

assocConversionF[list_] :=If[Length[Position[list, Rule, {2}]] > 0, Association[list], list]

listL = ReverseSortBy[Union[DeleteCases[Position[tst, List][[All, ;; -2]], {}]], Length@# &]

Association[MapAt[assocConversionF, tst, listL]]

I hope this helps someone with a similar issue.

Answered by Andy Krock on May 2, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP