2016-10-14 8 views
9

मैं संस्करण 2.8 के साथ Symfony 2 परियोजना पर काम कर रहा हूँ और मैं निर्माण में उपयोग कर रहा हूँ घटक Serializer ->http://symfony.com/doc/current/components/serializer.htmldenormalize सिम्फोनी 2 serializer के साथ वस्तुओं में आंतरिक संरचना

मैं एक JSON संरचना एक वेब द्वारा प्रदान की है सर्विस। deserialization के बाद, मैं वस्तुओं में मेरी सामग्री को denormalize करना चाहता हूँ। यहां मेरी संरचना है (मॉडल/कार अनुप्रयोग संदर्भ में बनाना)।

[{ 
"0": { 
    "id": 0, 
    "code": 1, 
    "model": "modelA", 
    "make": { 
     "id": 0, 
     "code": 1, 
     "name": "makeA" 
    } 
    } 
} , { 
"1": { 
    "id": 1, 
    "code": 2, 
    "model": "modelB", 
    "make": { 
     "id": 0, 
     "code": 1, 
     "name": "makeA" 
    } 
    } 
}] 

मेरा विचार को भरने के लिए एक VehicleModel वस्तु जो एक VehicleMake वस्तु का संदर्भ होता है है।

// Retrieve data in JSON 
$data = ... 
$serializer = new Serializer([new ObjectNormalizer(), new ArrayDenormalizer()], [new JsonEncoder()]); 
$models = $serializer->deserialize($data, '\Namespace\VehicleModel[]', 'json'); 

परिणाम में, मेरा वस्तु VehicleModel सही ढंग से भर जाता है लेकिन $make तार्किक मुख्य/मान सरणी है:

class VehicleModel { 
    public $id; 
    public $code; 
    public $model; 
    public $make; // VehicleMake 
} 

यहाँ मैं क्या कर रहा है। यहां मैं इसके बजाय VehicleMake चाहता हूं।

क्या ऐसा करने का कोई तरीका है?

Thx

उत्तर

5

ObjectNormalizer अधिक विन्यास की जरूरत है। आपको कम से कम PropertyTypeExtractorInterface प्रकार के चौथे पैरामीटर की आपूर्ति करने की आवश्यकता होगी।

<?php 
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; 
use Symfony\Component\PropertyInfo\Type; 
use Symfony\Component\Serializer\Encoder\JsonEncoder; 
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer; 
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; 
use Symfony\Component\Serializer\Serializer; 

$a = new VehicleModel(); 
$a->id = 0; 
$a->code = 1; 
$a->model = 'modalA'; 
$a->make = new VehicleMake(); 
$a->make->id = 0; 
$a->make->code = 1; 
$a->make->name = 'makeA'; 

$b = new VehicleModel(); 
$b->id = 1; 
$b->code = 2; 
$b->model = 'modelB'; 
$b->make = new VehicleMake(); 
$b->make->id = 0; 
$b->make->code = 1; 
$b->make->name = 'makeA'; 

$data = [$a, $b]; 

$serializer = new Serializer(
    [new ObjectNormalizer(null, null, null, new class implements PropertyTypeExtractorInterface { 
     /** 
     * {@inheritdoc} 
     */ 
     public function getTypes($class, $property, array $context = array()) 
     { 
      if (!is_a($class, VehicleModel::class, true)) { 
       return null; 
      } 

      if ('make' !== $property) { 
       return null; 
      } 

      return [ 
       new Type(Type::BUILTIN_TYPE_OBJECT, true, VehicleMake::class) 
      ]; 
     } 
    }), new ArrayDenormalizer()], 
    [new JsonEncoder()] 
); 

$json = $serializer->serialize($data, 'json'); 
print_r($json); 

$models = $serializer->deserialize($json, VehicleModel::class . '[]', 'json'); 
print_r($models); 

नोट अपने उदाहरण json में, पहली प्रविष्टि make के लिए मूल्य के रूप में एक सरणी है कि:

यहाँ एक (बल्कि hacky) उदाहरण दिया गया है। मैंने इसे टाइपो के रूप में लिया, अगर यह जानबूझकर है, तो कृपया एक टिप्पणी छोड़ दें।

यह अधिक स्वचालित बनाने के लिए आप PhpDocExtractor के साथ प्रयोग करना चाहेंगे।

+0

आप सही हैं मेरे पास मेरे जेसन में एक टाइपो है। मैंने अपना प्रश्न अपडेट किया। –

+0

ऑब्जेक्ट नॉर्मलिसर को कन्स्ट्रक्टर में केवल 3 तर्कों की आवश्यकता होती है और तीसरा एक PropertyAccessorInterface लागू करता है, है ना? –

+0

ओह, मैंने केवल एसएफ 3 पर इसका परीक्षण किया। तो एपीआई में बदलाव हो सकता है। यदि v2.8 में कोई प्रकार निकालने वाला कोई तरीका नहीं है, तो यह उत्तर आपके लिए उपयुक्त नहीं हो सकता है। – Yoshi

3

ऐसे मामलों में जब आपको denormalization में अधिक लचीलापन की आवश्यकता होती है तो अपने स्वयं के denormalizers बनाने के लिए अच्छा है।

$serializer = new Serializer(
    [ 
    new ArrayNormalizer(), 
    new VehicleDenormalizer(), 
    new VehicleMakeDenormalizer() 
    ], [ 
    new JsonEncoder() 
    ] 
); 
$models = $serializer->deserialize(
    $data, 
    '\Namespace\VehicleModel[]', 
    'json' 
); 
यहाँ

ऐसे denormalizer

class VehicleDenormalizer implements DenormalizerInterface, DenormalizerAwareInterface 
    { 
     public function denormalize($data, $class, $format, $context) 
     { 
     $vehicle = new VehicleModel(); 
     ... 
     $vehicleMake = $this->denormalizer->denormalize(
      $data->make, 
      VehicleMake::class, 
      $format, 
      $context 
     ); 
     $vehicle->setMake($vehicleMake); 
     ... 
     } 
    } 

के किसी न किसी कोड मैं केवल हम $this->denormalizer->denormalize पर भरोसा करना चाहिए पर संदेह (जो ठीक से सिर्फ इसलिए कि हम Symfony\Component\Serializer\Serializer का उपयोग काम करता है) है या हम स्पष्ट रूप से VehicleDenormalizer

में VehicleMakeDenormalizer इंजेक्षन चाहिए
$vehicleDenormalizer = new VehicleDenormalizer(); 
$vehicleDenormalizer->setVehicleMakeDenormalizer(new VehicleMakeDenormalizer()); 
संबंधित मुद्दे