16

I am trying to read a .json file from a web server. The JSON i am receiving from the server is reported to be invalid at http://jsonlint.com/ :

{
    preOpen: "900",
    preClose: "908",
    mktOpen: "915",
    mktClose: "1530",
    corrOpen: "1540",
    corrClose: "1600",
    mktStatusCode: "3",
    status: "MARKET OPEN",
    time: "Jan 11, 2012 12:32:14",
    data: [
        {
            name: "S&P CNX NIFTY Pre Open",
            lastPrice: "4,863.15",
            change: "13.60",
            pChange: "0.28",
            imgFileName: "S&P_CNX_NIFTY_Pre_Open_open.png"
        },
        {
            name: "S&P CNX NIFTY",
            lastPrice: "4,871.15",
            change: "21.60",
            pChange: "0.45",
            imgFileName: "S&P_CNX_NIFTY_open.png"
        },
        {
            name: "CNX NIFTY JUNIOR",
            lastPrice: "8,940.05",
            change: "91.90",
            pChange: "1.04",
            imgFileName: "CNX_NIFTY_JUNIOR_open.png"
        },
        {
            name: "BANK NIFTY",
            lastPrice: "8,816.15",
            change: "81.10",
            pChange: "0.93",
            imgFileName: "BANK_NIFTY_open.png"
        },
        {
            name: "INDIA VIX",
            lastPrice: "24.18",
            change: "0.18",
            pChange: "0.75",
            imgFileName: "INDIA_VIX_open.png"
        },
        {
            name: "CNX 100",
            lastPrice: "4,729.25",
            change: "25.05",
            pChange: "0.53",
            imgFileName: "CNX_100_open.png"
        },
        {
            name: "S&P CNX DEFTY",
            lastPrice: "3,265.00",
            change: "41.70",
            pChange: "1.29",
            imgFileName: "S&P_CNX_DEFTY_open.png"
        },
        {
            name: "S&P CNX 500",
            lastPrice: "3,811.75",
            change: "26.40",
            pChange: "0.70",
            imgFileName: "S&P_CNX_500_open.png"
        },
        {
            name: "CNX MIDCAP",
            lastPrice: "6,548.20",
            change: "80.65",
            pChange: "1.25",
            imgFileName: "CNX_MIDCAP_open.png"
        },
        {
            name: "NIFTY MIDCAP 50",
            lastPrice: "1,937.20",
            change: "21.30",
            pChange: "1.11",
            imgFileName: "NIFTY_MIDCAP_50_open.png"
        },
        {
            name: "CNX INFRA",
            lastPrice: "2,273.60",
            change: "8.50",
            pChange: "0.38",
            imgFileName: "CNX_INFRA_open.png"
        },
        {
            name: "CNX REALTY",
            lastPrice: "207.85",
            change: "8.10",
            pChange: "4.06",
            imgFileName: "CNX_REALTY_open.png"
        },
        {
            name: "CNX ENERGY",
            lastPrice: "7,300.55",
            change: "37.10",
            pChange: "0.51",
            imgFileName: "CNX_ENERGY_open.png"
        },
        {
            name: "CNX FMCG",
            lastPrice: "10,308.90",
            change: "10.90",
            pChange: "0.11",
            imgFileName: "CNX_FMCG_open.png"
        },
        {
            name: "CNX MNC",
            lastPrice: "4,660.35",
            change: "30.40",
            pChange: "0.66",
            imgFileName: "CNX_MNC_open.png"
        },
        {
            name: "CNX PHARMA",
            lastPrice: "4,743.15",
            change: "-4.15",
            pChange: "-0.09",
            imgFileName: "CNX_PHARMA_open.png"
        },
        {
            name: "CNX PSE",
            lastPrice: "2,753.90",
            change: "14.60",
            pChange: "0.53",
            imgFileName: "CNX_PSE_open.png"
        },
        {
            name: "CNX PSU BANK",
            lastPrice: "2,847.95",
            change: "22.80",
            pChange: "0.81",
            imgFileName: "CNX_PSU_BANK_open.png"
        },
        {
            name: "CNX SERVICE",
            lastPrice: "5,933.65",
            change: "21.65",
            pChange: "0.37",
            imgFileName: "CNX_SERVICE_open.png"
        },
        {
            name: "CNX IT",
            lastPrice: "6,300.35",
            change: "-31.40",
            pChange: "-0.50",
            imgFileName: "CNX_IT_open.png"
        },
        {
            name: "CNX SMALLCAP",
            lastPrice: "2,981.80",
            change: "49.85",
            pChange: "1.70",
            imgFileName: "CNX_SMALLCAP_open.png"
        },
        {
            name: "CNX 200",
            lastPrice: "2,432.05",
            change: "14.35",
            pChange: "0.59",
            imgFileName: "CNX_200_open.png"
        },
        {
            name: "CNX AUTO",
            lastPrice: "3,497.60",
            change: "4.05",
            pChange: "0.12",
            imgFileName: "CNX_AUTO_open.png"
        },
        {
            name: "CNX MEDIA",
            lastPrice: "1,147.30",
            change: "23.35",
            pChange: "2.08",
            imgFileName: "CNX_MEDIA_open.png"
        },
        {
            name: "CNX METAL",
            lastPrice: "2,746.95",
            change: "60.60",
            pChange: "2.26",
            imgFileName: "CNX_METAL_open.png"
        }
    ]
}

Its displaying the following test result :

Parse error on line 1:
{    preOpen: "900",    
-----^
Expecting 'STRING', '}'

How can i convert it to VALID JSON before parsing it using PHP ??

Sandy505
  • 888
  • 3
  • 15
  • 26
  • The keys must be in double quotes - so preOpen: "900" must be "preOpen": "900", and so on. Not sure how to fix it if you don't have control over json source. You might use regex - look for a single word before the colon and include it in double quotes. – AR. Jan 11 '12 at 07:30

5 Answers5

11

All keys (preOpen, preClose, ...) have to be strings, so they need double-quotes around.

{
    "preOpen": "900",
    "preClose": "908",
    ...
}

=== UPDATE ===

If you have an invalid Json-String you can convert it with following script:

$sInvalidJson = '{
    preOpen: "900",
    preClose: "908"
}';
$sValidJson = preg_replace("/(\n[\t ]*)([^\t ]+):/", "$1\"$2\":", $sInvalidJson);

Also see this example.

(This script only works with the invalid JSON described above, otherwise the pattern has to be changed.)

=== UPDATE ===

$sInvalidJson = '{preOpen:"900",preClose:"908",mktOpen:"915",mktClose:"1530",corrOpen:"1540",corrClose:"1600",mktStatusCode:"3",status:"MARKET OPEN",time:"Jan 11, 2012 14:25:15",data:[{name:"S&P CNX NIFTY Pre Open",lastPrice:"4,863.15",change:"13.60",pChange:"0.28",imgFileName:"S&P_CNX_NIFTY_Pre_Open_open.png"},{name:"S&P CNX NIFTY",lastPrice:"4,847.85",change:"-1.70",pChange:"-0.04",imgFileName:"S&P_CNX_NIFTY_open.png"},{name:"CNX NIFTY JUNIOR",lastPrice:"8,917.00",change:"68.85",pChange:"0.78",imgFileName:"CNX_NIFTY_JUNIOR_open.png"},{name:"BANK NIFTY",lastPrice:"8,768.75",change:"33.70",pChange:"0.39",imgFileName:"BANK_NIFTY_open.png"},{name:"INDIA VIX",lastPrice:"24.61",change:"0.61",pChange:"2.54",imgFileName:"INDIA_VIX_open.png"},{name:"CNX 100",lastPrice:"4,707.85",change:"3.65",pChange:"0.08",imgFileName:"CNX_100_open.png"},{name:"S&P CNX DEFTY",lastPrice:"3,253.50",change:"30.20",pChange:"0.94",imgFileName:"S&P_CNX_DEFTY_open.png"},{name:"S&P CNX 500",lastPrice:"3,795.40",change:"10.05",pChange:"0.27",imgFileName:"S&P_CNX_500_open.png"},{name:"CNX MIDCAP",lastPrice:"6,524.90",change:"57.35",pChange:"0.89",imgFileName:"CNX_MIDCAP_open.png"},{name:"NIFTY MIDCAP 50",lastPrice:"1,926.55",change:"10.65",pChange:"0.56",imgFileName:"NIFTY_MIDCAP_50_open.png"},{name:"CNX INFRA",lastPrice:"2,262.05",change:"-3.05",pChange:"-0.13",imgFileName:"CNX_INFRA_open.png"},{name:"CNX REALTY",lastPrice:"207.70",change:"7.95",pChange:"3.98",imgFileName:"CNX_REALTY_open.png"},{name:"CNX ENERGY",lastPrice:"7,301.05",change:"37.60",pChange:"0.52",imgFileName:"CNX_ENERGY_open.png"},{name:"CNX FMCG",lastPrice:"10,235.35",change:"-62.65",pChange:"-0.61",imgFileName:"CNX_FMCG_open.png"},{name:"CNX MNC",lastPrice:"4,631.55",change:"1.60",pChange:"0.03",imgFileName:"CNX_MNC_open.png"},{name:"CNX PHARMA",lastPrice:"4,749.95",change:"2.65",pChange:"0.06",imgFileName:"CNX_PHARMA_open.png"},{name:"CNX PSE",lastPrice:"2,744.85",change:"5.55",pChange:"0.20",imgFileName:"CNX_PSE_open.png"},{name:"CNX PSU BANK",lastPrice:"2,841.10",change:"15.95",pChange:"0.56",imgFileName:"CNX_PSU_BANK_open.png"},{name:"CNX SERVICE",lastPrice:"5,900.60",change:"-11.40",pChange:"-0.19",imgFileName:"CNX_SERVICE_open.png"},{name:"CNX IT",lastPrice:"6,262.10",change:"-69.65",pChange:"-1.10",imgFileName:"CNX_IT_open.png"},{name:"CNX SMALLCAP",lastPrice:"2,963.90",change:"31.95",pChange:"1.09",imgFileName:"CNX_SMALLCAP_open.png"},{name:"CNX 200",lastPrice:"2,421.50",change:"3.80",pChange:"0.16",imgFileName:"CNX_200_open.png"},{name:"CNX AUTO",lastPrice:"3,484.30",change:"-9.25",pChange:"-0.26",imgFileName:"CNX_AUTO_open.png"},{name:"CNX MEDIA",lastPrice:"1,139.60",change:"15.65",pChange:"1.39",imgFileName:"CNX_MEDIA_open.png"},{name:"CNX METAL",lastPrice:"2,726.75",change:"40.40",pChange:"1.50",imgFileName:"CNX_METAL_open.png"}]}';
$sValidJson = preg_replace("/([{,])([a-zA-Z][^: ]+):/", "$1\"$2\":", $sInvalidJson);

Also this updated example.

scessor
  • 15,995
  • 4
  • 43
  • 54
  • Very nice answer. Works very good, except for the part `time: "Jan 11, 2012 12:32:14",` which is screwed up. – DKSan Jan 11 '12 at 07:43
  • i m using the following code with no success : ` $url = 'http://abc/abc.json'; $session = curl_init($url); curl_setopt($session,CURLOPT_USERAGENT,'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13'); curl_setopt ($session, CURLOPT_POST, true); curl_setopt($session, CURLOPT_HEADER, false); curl_setopt($session, CURLOPT_RETURNTRANSFER, true); $json = curl_exec($session); echo $json; echo "
    "; $sValidJson = preg_replace("/(\n[\t ]*)([^\t ]+):/", "$1\"$2\":", $json); echo $sValidJson;` I am getting the same output !!!!
    – Sandy505 Jan 11 '12 at 08:05
  • I think the json is a little different (e.g. the newlines), then the pattern doesn't work. I need exactly the content of the json-string. – scessor Jan 11 '12 at 08:28
  • Do you really need to convert the string? If you only need to add the json-string to a javascript output, you don't need to convert it, because this is valid javascript code. Otherwise if you want to decode the json in PHP, you really should do it. Then I need the string exactly. – scessor Jan 11 '12 at 08:37
  • this is the link from where i need to parse the json. [JSON](http://www.nseindia.com/homepage/Indices1.json) I need to decode this json on my php file. – Sandy505 Jan 11 '12 at 08:42
3

Most solutions offered have a number of problems, mainly with colons.

I wrote a json to array function that overcomes this problem.

It also checks for round braces around the json string and removes it pre json_decode.

Here is the function:

function jsonDecode($string, $assoc=true, $fixNames=true){
  if(strpos($string, '(') === 0){
    $string = substr($string, 1, strlen($string) - 2); // remove outer ( and )
  }
  if($fixNames){
    $string = preg_replace("/(?<!\"|'|\w)([a-zA-Z0-9_]+?)(?!\"|'|\w)\s?:/", "\"$1\":", $string);
  }
  return json_decode($string, $assoc);
}

it also checks for blank spaces before colons and excludes them from the variable names.

Here is an example string I tested:

({style:"border: 5px solid pink;", class:"test", "correct":"value", test:true, var5:"some escaped\" string"})

After conversion:

Array
(
    [style] => border: 5px solid pink;
    [class] => test
    [correct] => value
    [test] => 1
    [var5] => some escaped" string
)

So far it looks bullet proof.

Let me know if you find a hole.

Dieter Gribnitz
  • 5,062
  • 2
  • 41
  • 38
3

I believe that proper JSON strings need double quotes around all the key names as well. What you show is a valid JavaScript object, but when stringified into JSON should have double quotes around all the keys.

random-forest-cat
  • 33,652
  • 11
  • 120
  • 99
davidethell
  • 11,708
  • 6
  • 43
  • 63
  • Yeah, by using `JSON.stringify(eval({ preOpen: "900", ....}))`, valid JSON is returned. @Sandy505 However using eval is dangerous, especially if data comes from 3rd party source as you don't know what could be passed. It could as well be malicious code injected in your webpage. Anyway thaths not the PHP side. – Janis Veinbergs Jan 11 '12 at 07:36
1

Yea, it's malformed - missing quotes around key names. You need to parse it yourself as string... or change file on server.

Roman Newaza
  • 11,405
  • 11
  • 58
  • 89
0

The property names need to be quoted. See http://json.org/example.html for an example. I would change the server to produce proper JSON.

It should be producing something like { "preOPen": "900", .... }

Richard Schneider
  • 34,944
  • 9
  • 57
  • 73