2015-06-02 24 views
5

Jak wspomniano w dokumentacji PHP, gdy json_decode ing struktury danych zawierających długie liczby całkowite, zostaną one przekonwertowane na zmienne. Rozwiązaniem jest użycie JSON_BIGINT_AS_STRING, która zachowuje je jako ciągi. Kiedy json_encode ing takie wartości, JSON_NUMERIC_CHECK zakoduje te numery z powrotem do dużych liczb całkowitych:json_decode I json_encode długie liczby całkowite bez utraty danych

$json = '{"foo":283675428357628352}'; 
$obj = json_decode($json, false, JSON_BIGINT_AS_STRING); 
$json2 = json_encode($obj, JSON_NUMERIC_CHECK); 
var_dump($json === $json2); // true 

Stosując tę ​​metodę do prawidłowego obie strony danych jest podatna na błędy. Jeśli właściwość zawiera '123', łańcuch liczbowy, który powinien pozostać ciągiem znaków, zostanie zakodowany na liczbę całkowitą.

Chcę pobrać obiekt z serwera, zmodyfikować jedną właściwość i przywrócić całą strukturę danych. Muszę zachować oryginalne typy. Nie chcę utrzymywać właściwości innych niż te, którymi manipuluję.

Czy istnieje rzeczywiste obejście tego problemu? PHP nie ma już żadnych problemów z dużymi intami, ale rutyna json_decode wydaje się być przestarzała.

+1

Sprawdziłeś podobny wątek http://stackoverflow.com/questions/15659325/json-bigint-as-string-backporting –

+0

To trochę zagmatwało to, o co prosisz. Podsumowując: chcesz "json_decode" zestaw danych, zmienić niektóre właściwości, a następnie "json_encode" to jeszcze raz; Twoim problemem jest to, że duże liczby całkowite zamieniają się w pływaki lub łańcuchy. Czy mam to prawidłowe? – deceze

+0

Tak, ale sugeruje się użycie biblioteki innej firmy. Lubię utrzymywać małe aplikacje. – SuperNova

Odpowiedz

3

Dopóki twoja wersja PHP może rzeczywiście obsłużyć duże liczby całkowite, co oznacza, jeśli używasz wersji 64-bitowej PHP (na czymś other than Windows), json_decode ma żadnego problemu z nim:

$json = '{"foo":9223372036854775807}'; 
$obj = json_decode($json); 
$json2 = json_encode($obj); 

var_dump(PHP_INT_MAX, $obj, $json2); 

int(9223372036854775807) 
object(stdClass)#1 (1) { 
    ["foo"]=> 
    int(9223372036854775807) 
} 
string(27) "{"foo":9223372036854775807}" 

Jeśli wartości całkowite, które musisz obsłużyć, przekraczają wartość PHP_INT_MAX PHP, po prostu nie mogą reprezentować ich w rodzimych typach PHP. Więc nie ma sposobu, aby rozwiązać tę zagadkę; nie można używać rodzimych typów do śledzenia poprawnego typu i nie można zastępować innych typów (np. łańcuchów zamiast liczb całkowitych), ponieważ jest to niejednoznaczne podczas kodowania z powrotem do JSON.

W tym przypadku będziesz musiał wymyślić własny mechanizm śledzenia poprawnych typów dla każdej właściwości i obsługiwać taką serializację za pomocą niestandardowego kodera/dekodera. Na przykład, musisz napisać niestandardowy dekoder JSON, który może dekodować do niestandardowej klasy, takiej jak new JsonInteger('9223372036854775808'), a Twój niestandardowy koder rozpozna ten typ i zakoduje go do wartości JSON 9223372036854775808.

Nie ma czegoś takiego wbudowanego w PHP.

+0

Używam windows 8.1 (64-bitowy), apache v2.4 (64-bitowy) i php v5.6.9 (64-bitowy). – SuperNova

+2

Cóż, zastrzeżenie: [* "64-bitowe platformy mają zwykle maksymalną wartość około 9E18, z wyjątkiem systemu Windows, który jest zawsze 32-bitowy." *] (Http://php.net/manual/en/language.types .integer.php) – deceze

+0

Uhm, myślę, że nie ma rozwiązania. Ale chciałbym, żebyś zdobył reputację. Dziękuję Ci. Mój system produkcyjny używa Linuksa i jest w porządku. – SuperNova