将嵌套的json对象转换为php字符串而不剥离值

时间:2014-07-23 06:21:01

标签: php json

我收到带有以下JSON对象的HTTP帖子:

{"notification":{"version":6.0,"attemptCount":0,"role":"VENDOR","site":"nicholeen","receipt":"********","currency":"USD","transactionType":"TEST","transactionTime":1406070122781,"paymentMethod":"VISA","totalProductAmount":1.00,"totalTaxAmount":0.00,"totalShippingAmount":0.00,"customer":{"shipping":{"firstName":"TEST","lastName":"USER","fullName":"Test User","email":"testuser@somesite.com","address":{}},"billing":{"firstName":"TEST","lastName":"USER","fullName":"Test User","email":"testuser@somesite.com","address":{}}},"lineItems":[{"itemNo":"1","productTitle":"A passed in title","shippable":false,"recurring":false,"customerProductAmount":1.00,"customerTaxAmount":0.00}]},"verification":"2745A502"}

我需要转换"通知"将JSON对象转换为分配给PHP变量的JSON字符串,而不会丢失任何数据,包括小数。

目前我正在使用$ipn_raw = file_get_contents('php://input');接收IPN。 然后我json_decode将JSON编码为PHP变量,然后使用json_encode重新编码通知部分。这是代码:

$ipn_raw = file_get_contents('php://input');
$ipn = json_decode($ipn_raw);
$notification = $ipn['notification'];
$result = json_encode($notification);

然而,结果剥离了一些值,给出了以下内容:

{"version":6,"attemptCount":0,"role":"VENDOR","site":"nicholeen","receipt":"********","currency":"USD","transactionType":"TEST","transactionTime":1406095846441,"paymentMethod":"VISA","totalProductAmount":1,"totalTaxAmount":0,"totalShippingAmount":0,"customer":{"shipping":{"firstName":"TEST","lastName":"USER","fullName":"Test User","email":"testuser@somesite.com","address":[]},"billing":{"firstName":"TEST","lastName":"USER","fullName":"Test User","email":"testuser@somesite.com","address":[]}},"lineItems":[{"itemNo":"1","productTitle":"A passed in title","shippable":false,"recurring":false,"customerProductAmount":1,"customerTaxAmount":0}]}

你可以看到版本6.0现在只是版本6,totalProductAmount是1.00,现在是1,等等。

如何在结果中没有任何值更改的情况下执行此操作?

谢谢!

根据请求,这里有一些额外的背景信息,说明为什么我需要将所有内容与原始内容保持不变。 Clickbank为我提供了以下信息,以便创建必要的SHA 1哈希来验证我从他们那里收到的第6版IPN(参见https://support.clickbank.com/entries/22803622-Instant-Notification-Service

1)使用JSON库/ DSL从IPN中提取“通知”JSON对象。 2)转换"通知"将JSON对象转换为JSON字符串。该字符串应以大括号开头{并以大括号结束},因为它是JSON对象的表示。 3)在通知对象的结束大括号之后将密钥直接附加到字符串上。没有空格或分隔符。 4)SHA 1散列在步骤3中创建的字符串。 5)获取在步骤4中创建的哈希的前8个字符。这是"验证"的值。 v6 IPN中的字段。

如果需要,我可以为其余步骤提供所有代码,但此时我唯一遇到问题的部分是将字符串中的通知对象单独获取。

3 个答案:

答案 0 :(得分:2)

你在问什么(考虑到你正在对JSON对象的字符串表示进行哈希处理),你需要通过字符串操作方法(例如正则表达式)提取JSON的相关部分):

$result = preg_replace(array('^\{[^{]', '[^}]\}$'), '', $in);

这将在开始时将所有内容剥离到第二个大括号,并从最后的第二个大括号中删除所有内容。 (但显然只有你的JSON具有这种确切的格式才有效,即通知是唯一的嵌套对象,第一个对象,以及之后的所有内容都不包含}(特别是验证码))


似乎有一个关于此问题的“错误”报告:https://bugs.php.net/bug.php?id=50224,虽然似乎字符串化6.0是预期的行为,JavaScript也做同样的事情。另请参阅此相关问题:PHP function json_decode decodes float value with zeros after point as int

答案 1 :(得分:1)

问题是:6.06从值的角度来看都是相同的浮点数。因此,在解码时,PHP将丢失此十进制格式点。因此,在您第一次json_decode()来电时,您已经丢失了有关小数点数的数据。

解决方法可能是使用quites将您的值放在原始源json中,将它们转换为字符串并以PHP格式存储在PHP中。它就像:

$jsonRaw = '{"notification":{"version":6.0,"attemptCount":0,"role":"VENDOR","site":"nicholeen","receipt":"********","currency":"USD","transactionType":"TEST","transactionTime":1406070122781,"paymentMethod":"VISA","totalProductAmount":1.00,"totalTaxAmount":0.00,"totalShippingAmount":0.00,"customer":{"shipping":{"firstName":"TEST","lastName":"USER","fullName":"Test User","email":"testuser@somesite.com","address":{}},"billing":{"firstName":"TEST","lastName":"USER","fullName":"Test User","email":"testuser@somesite.com","address":{}}},"lineItems":[{"itemNo":"1","productTitle":"A passed in title","shippable":false,"recurring":false,"customerProductAmount":1.00,"customerTaxAmount":0.00}]},"verification":"2745A502"}';

$jsonRaw = preg_replace('/(\b)([0-9]+\.[0-9]+)(\b)/', '$1"$2"$3', $jsonRaw);
$jsonObj = json_decode($jsonRaw);

所以现在你的对象会将你的值存储为 strings ,并且不会导致小数点丢失。当然,通过解码,你需要做反向的事情:

$notification = $jsonObj->notification;
$result       = json_encode($notification);
$result       = preg_replace('/"([0-9]+\.[0-9]+)"/', '$1', $result);

但这有一个缺陷:因为你会丢失有关实际字符串和浮点数的数据。因此,如果您的原始json包含 string ,例如"6.00"并且它意图是字符串,则此类转换将丢失该信息并使该值浮动。因此,如果你的数据包含这种形式的字符串,那么 - 是的,它不是要走的路(但是我怀疑没有实现你自己的json解析器就有一个简单的方法)

答案 2 :(得分:0)

对于任何有兴趣的人来说,这就是我最终使用的内容:

$json_ipn = preg_replace('({"notification":|,"verification"([\s\S]*))', '', $ipn_raw);